什么是JWT
JSON Web Token
,通过数字签名的方式,以json对象为载体,在不同服务端之间安全的传输信息
JWT有什么用
JWT最常见的场景就是授权认证,一旦用户登录,后续每个请求都将包含JWT,系统每次处理用户请求前,都要先进行JWT安全校验,通过之后在进行处理
JWT组成
JWT由3部分组成,用"."拼接
- Header(头部)
- Payload(载荷)
- Signature(签名)
三部分最终组合成完整的字符串,中间使用 . 分隔, 如下: - Header.Payload.Signature
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IuW8oOS4iSIsInJvbGUiOiJhZG1pbiIsInN1YiI6InRva2VuLXRlc3QiLCJleHAiOjE2ODM1NDg4ODcsImp0aSI6ImM0N2VlN2FmLWNkZTUtNGI2NC1iMzlmLWJlODNiYWY0NTI0NCJ9.eLGLfNl6Pt6se3MqaKI7u0mcxG5woUCwF_585W7l3WQ
-
Header
{ "typ":"JWT", "alg":"HS256" }
- Header部分是一个json对象,描述JWT的元数据
- alg:签名的算法(algorithm),默认是HMAC SHA256(简写 HS256)
- typ:令牌(token)类型(type),JWT令牌统一写成 JWT
- 最后,将上面的JSON对象使用Base64URL算法转成字符串
-
Payload
{ "sub":"1234567890", "name":"john", "admin":true }
- Payload部分也是一个JSON对象,用来存放实际需要传递的数据,JWT规定7个官方字段,供选用
- iss(issuer):签发人
- exp(expiration time):过期时间
- sub(subject):主题
- aud(audience):受众
- nbf(Not Before):生效时间
- iat(Issued At):签发时间
- jti(JWT ID):编号
- 注意,JWT默认是不加密的,任何人都可以读到,所以不要吧秘密信息放在这个部分
- 这个JSON对象也要使用Base64URL算法转成字符串
- Payload部分也是一个JSON对象,用来存放实际需要传递的数据,JWT规定7个官方字段,供选用
-
Signature
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), "secret");
- SIgnature部分是对前两部分的签名,防止数据篡改
- 首先,需要指定一个密钥(secret)。这个密钥只有服务端知道,不能泄露给用户
- 然后,使用Header里面指定的签名算法(默认是HMAC SHA256),按照上面的公式生成签名
案例测试
- 依赖引入
<!--jwt依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
- JWT生成token
@Test
public void jwtCreate() {
JwtBuilder builder = Jwts.builder();
String token = builder
//Header
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
//Payload
.claim("username", "张三")
.claim("role", "admin")
.setSubject("token-test")
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.setId(UUID.randomUUID().toString())
//signature
.signWith(SignatureAlgorithm.HS256, signature)
.compact();
System.out.println(token);
}
- JWT解密token
@Test
public void jwtParse() {
String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IuW8oOS4iSIsInJvbGUiOiJhZG1pbiIsInN1YiI6InRva2VuLXRlc3QiLCJleHAiOjE2ODM1NDg4ODcsImp0aSI6ImM0N2VlN2FmLWNkZTUtNGI2NC1iMzlmLWJlODNiYWY0NTI0NCJ9.eLGLfNl6Pt6se3MqaKI7u0mcxG5woUCwF_585W7l3WQ";
JwtParser parser = Jwts.parser();
Jws<Claims> claimsJws = parser.setSigningKey(signature).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
System.out.println("Subject: "+ claims.getSubject());
System.out.println("username: "+ claims.get("username"));
System.out.println("role: "+ claims.get("role"));
}