上文总览篇 中,相信大家已经对接下来要做的事情有了总体思路及印象。总言之我们要做的就只有两件事,一是授权,二即是鉴权。 让我们先从授权开始,何为授权?在这里简单地来讲就是要颁发token。何时颁发?毫无疑问,无非就是在登录/注册成功之后。 至于上文中提到的根据RefreshToken自动刷新AccessToken,我将之归置为token刷新,代码实现于后续篇章说明。 Here we go.
一、Maven配置 1 2 3 4 5 6 <!-- jwt --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>${java-jwt.version}</version> </dependency>
二、Application配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 server: port: 8001 spring: application: name: springboot-shiro-jwt-sso # profiles: springboot-shiro-jwt-sso ## Redis配置 - start redis: # Redis数据库索引(默认为0) database: 1 # Redis服务器地址 host: 127.0 .0.1 # Redis服务器连接端口 port: 6379 # Redis服务器连接密码(默认为空) # password: "doufuplus" # 连接超时时间(毫秒) timeout: 5000 jedis: pool: # 连接池最大连接数(使用负值表示没有限制) max-active: 8 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1 # 连接池中的最大空闲连接 max-idle: 8 # 连接池中的最小空闲连接 min-idle: 0 ## Redis配置 - end ## 时间格式配置 - start jackson: serialization: write-dates-as-timestamps: true ## 时间格式配置 - end ## product配置 - start info: app.name: springboot-shiro-jwt-sso company.name: doufuplus build.artifactId: $project.artifactId$ build.modelVersion: $project.modelVersion$ ## product配置 - end ## 日志配置 - start logging: level: com.nfgj.medical.service: DEBUG ## 日志配置 - end ## 其它配置 - start config: # JWT认证加密私钥(Base64加密) encrypt-jwtKey: U0JBUElOENhspJrzkyNjQ1NA # AccessToken过期时间(秒) accessToken-expireTime: 600 # RefreshToken过期时间(秒) refreshToken-expireTime: 604800 ## 其它配置 - end
三、颁发Token token的颁发并未有什么难度,主要是生成AccessToken放置于Header给前端。再生成RefreshToken保存于服务端即可。此处使用redis保存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @PostMapping ("/login" )public Result login (String account, String password, HttpServletResponse response) { try { if (!("doufuplus" .equals(account) && "123456" .equals(password))) { return new Result(ResultCode.PASSWORD_ERROR, "account or password error." ); } if (redis.hasKey(RedisConstant.PREFIX_SHIRO_CACHE + account)) { redis.del(RedisConstant.PREFIX_SHIRO_CACHE + account); } String currentTimeMillis = String.valueOf(System.currentTimeMillis()); redis.set(RedisConstant.PREFIX_SHIRO_REFRESH_TOKEN + account, currentTimeMillis, Integer.parseInt(refreshTokenExpireTime)); String token = JwtUtil.sign(account, currentTimeMillis); response.setHeader("Authorization" , token); response.setHeader("Access-Control-Expose-Headers" , "Authorization" ); return new Result().OK(); } catch (Exception e) { e.printStackTrace(); return new Result(ResultCode.ERROR, e.getMessage()); } }
四、清除Token 没有买卖就没有伤害,有登录就会有退出。token的清除主要是做两件事:
清除可能存在的shiro权限信息
清除RefreshToken
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @RequestMapping ("/logout" )public Result logout () { try { String token = "" ; Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String key = (String) headerNames.nextElement(); String value = request.getHeader(key); if ("Authorization" .equalsIgnoreCase(key)) { token = value; } } if (StringUtils.isBlank(token)) { return new Result(ResultCode.PARAM_ERROR); } String account = JwtUtil.getClaim(token, JwtConstant.ACCOUNT); if (StringUtils.isBlank(account)) { return new Result(ResultCode.NOT_LOGIN, "token失效或不正确." ); } if (redis.hasKey(RedisConstant.PREFIX_SHIRO_CACHE + account)) { redis.del(RedisConstant.PREFIX_SHIRO_CACHE + account); } redis.del(RedisConstant.PREFIX_SHIRO_REFRESH_TOKEN + account); return new Result().OK(); } catch (Exception e) { e.printStackTrace(); return new Result(ResultCode.ERROR, e.getMessage()); } }
五、演示说明
登录成功,返回10200
查看Header,Authorization返回AccessToken信息