一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
-
如何实现单点登录
-
实现jwt机制
-
自己简单实现jwt。(实现MD5类型的举例,由于代码比较简单,所以不贴代码了)
-
准备header标头json字符串 {"typ":"JWT","alg":"HS256"}
-
准备好payload的自定义参数json字符串{"userId":"001"}
-
准备好MD5算法的盐值 String SING="123321"
-
生成JWT
String headerBase64=Base64.encodeBase64(准备好的标头字符串) String payloadBase64=Base64.encodeBase64(准备好的payload字符串) String singnature=MD5(headerBase64+payloadBase64+准备好MD5算法的盐值) String jwt=headerBase64+"."+payloadBase64+"."singnature -
验证JWT
String jwtArray=jwt.split("."); //根据点.切割字符串 if(jwtArray[2].equals(MD5(jwtArray[0]+jwtArray[1]+准备好MD5算法的盐值))){ 有效 }else{ 无效 } //TODO 额外的payload中自定义的参数的判断,比如有效时间判断 -
将要超时主动续期和注销退出登录功能的额外实现(TODO)
-
-
使用开源框架实现jwt。(这里选择使用 Auth0 Java JWT 实现举例)
-
添加依赖
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.2</version> </dependency> <!-- 以下两个依赖非必须,当生成token失败的时候根据报错如果是缺失这个才需要加 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>- 生成jwt
// 生成 JWT Token Algorithm algorithm = Algorithm.HMAC256(SING); String token = JWT.create() .withHeader(new HashMap<>()) //自定义额外标头参数 map类型 .withClaim("payloadData1", 1) //自定义额外负载参数 int类型 .withClaim("payloadData2", "2") //自定义额外负载参数 String类型 .withClaim("payloadData3", true) //自定义额外负载参数 Boolean类型 .withIssuer("Self") // 预定义payload字段:签发者的名称,没设置则不会出现在负载中。取的时候也会返回null .withSubject("Test Auth0 JWT") // 预定义payload字段:jwt所面向的用户的值,没设置则不会出现在负载中。取的时候也会返回null .withAudience("Audience X", "Audience Y", "Audience Z") // 预定义payload字段:该jwt由谁接收,没设置则不会出现在负载中。取的时候也会返回null .withExpiresAt(DateUtil.getChangeDate(20, TimeUnit.MINUTES)) //jwt过期时间(某个时间点之后就失效了) .withNotBefore(DateUtil.getChangeDate(0, null)) // 定义在什么时间之前的时间(时间倒着走是不会过期的),该jwt都是不可用的. .withIssuedAt(DateUtil.getChangeDate(0, null)) //生成签名的时间 .withJWTId("jwt-id-1") .sign(algorithm);-
验证jwt。(JWT.require(algorithm)里面的algorithm要传上面对应的加密算法出来的algorithm)
-
-
-
实现各个子系统直接的单点登录
- 如果子系统的盐值相同,就可以对同一个jwt进行相同的是否有效的判断。所以这个部分比较简单。每个子系统用相同的盐值实现上面第3不验证jwt即可。
-
主动注销和过期有效性的处理
-
用户主动退出登录,使得jwt失效
为了防止jwt在过期时间内一直有效,需要加上注销jwt的功能。由于我想要的是那种服务器或者redis挂了,功能也能用的方式。 又会回到有状态的情况。暂时还没有想到好的解决办法(持久化、读数据库啥的就算了)。 //暂时用客户端清除jwt实现 。。。。。。。。 -
如果jwt快要过期,则对jwt进行续期
为了防止jwt用着用着突然过期,需要加上续期功能if( decodedJWT.getExpiresAt()-now<3分钟){ //生成新的jwt返回给客户端存储 }
-
-