Json web token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519)。该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
组成
由句号分隔的三段base64串b1.b2.b3,如:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
- header:头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等,为json格式。用base64转成一个串b1。
- paload:放入一些自定义信息,为json格式。用base64转成一个串b2。jwt预放入了五个字段:
- iss: 该JWT的签发者
- sub: 该JWT所面向的用户
- aud: 接收该JWT的一方
- exp(expires): 什么时候过期,这里是一个Unix时间戳
- iat(issued at): 在什么时候签发的
- signature:用header中所声明的加密方法(需要为之提供一个key)将 base64( header).base64(paload) 加密得到第三个base64串b3。
校验原理
由于用base64,所以可以直接逆转码提取header、payload信息。服务端收到token后会根据header声明的加密算法再计算下signature,若与token中的signature不同则当成未授权的token。
功能
(与传统session或token的区别):
- 适合用于向Web应用传递一些非敏感信息如userId、isAdmin等,不能包含密码等敏感信息;
- 本身具备失效判断机制:根据串本身就能知道该token是否失效,而不用自己出来了;
- 服务端不需要存储token,而是分散给各个客户端存储,session机制则要。有利就有弊,jwt增加了计算开销如加解密,但总的利大于弊。
- 服务端能识别被篡改的token,所以只要token校验通过,就可以把里面封装的信息当成可信的。
使用示例
依赖:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.7.0</version> </dependency>
代码:
1 import java.security.Key; 2 3 import io.jsonwebtoken.Claims; 4 import io.jsonwebtoken.ExpiredJwtException; 5 import io.jsonwebtoken.Jws; 6 import io.jsonwebtoken.Jwts; 7 import io.jsonwebtoken.MalformedJwtException; 8 import io.jsonwebtoken.SignatureAlgorithm; 9 import io.jsonwebtoken.SignatureException; 10 import io.jsonwebtoken.impl.crypto.MacProvider; 11 12 public class JWTtest { 13 14 public static void main(String[] args) { 15 // 生成jwt 16 Key key = MacProvider.generateKey();// 这里是加密解密的key。 17 String compactJws = Jwts.builder()// 返回的字符串便是我们的jwt串了 18 .setSubject("Joe")// 设置主题 19 .claim("studentId", 2)// 添加自定义数据 20 .signWith(SignatureAlgorithm.HS512, key)// 设置算法(必须) 21 .compact();// 这个是全部设置完成后拼成jwt串的方法 22 System.out.println("the generated token is: " + compactJws); 23 24 // 解析jwt 25 try { 26 27 Jws<Claims> parseClaimsJws = Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws);// compactJws为jwt字符串 28 Claims body = parseClaimsJws.getBody();// 得到body后我们可以从body中获取我们需要的信息 29 // 比如 获取主题,当然,这是我们在生成jwt字符串的时候就已经存进来的 30 String subject = body.getSubject(); 31 System.out.println("the subject is: " + subject); 32 System.out.println("the studentId is: " + body.get("studentId")); 33 34 // OK, we can trust this JWT 35 36 } catch (SignatureException | MalformedJwtException e) { 37 // TODO: handle exception 38 // don‘t trust the JWT! 39 // jwt 解析错误 40 } catch (ExpiredJwtException e) { 41 // TODO: handle exception 42 // jwt 已经过期,在设置jwt的时候如果设置了过期时间,这里会自动判断jwt是否已经过期,如果过期则会抛出这个异常,我们可以抓住这个异常并作相关处理。 43 } 44 } 45 }
参考资料
- Json Web Token:http://blog.leapoahead.com/2015/09/06/understanding-jwt/
- Json Web Token单点登录:http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/
原文地址:https://www.cnblogs.com/z-sm/p/9125995.html
时间: 2024-10-29 08:14:17