jwt令牌的组成
1.Header:记录令牌类型,签名算法等,例如:{"alg":"HS256","type":"JWT"}
2.Payload(有效载荷),携带一些自定义信息,默认信息等,例如:{"id":"1","username":"Tom"}
3.Signature(签名):防止Token被篡改,确保安全性,将Header,Payload一并加入指定秘钥中,通过指定签名算法计算而来.
引入依赖
第一种
在这个版本中对签名长度有了一定的要求,必须要达到256个字节,如果你不想使用这么长的签名的话,可以使用第二种
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-gson</artifactId>
<version>0.11.5</version>
</dependency>
第二种
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
第二种不会爆长度错误
生成jwt令牌
传递的参数,签名,有效时间,携带的信息
1.签名算法用SignatureAlgorithm指定
2.有效荷载使用Map<String,Object>claim
3.指定签名字符串
/**
* 生成jwt
* 使用Hs256算法, 私匙使用固定秘钥
*
* @param secretKey jwt秘钥
* @param ttlMillis jwt过期时间(毫秒)
* @param claims 设置的信息
* @return
*/
public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
// 指定签名的时候使用的签名算法,也就是header那部分
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 生成JWT的时间
long expMillis = System.currentTimeMillis() + ttlMillis;
Date exp = new Date(expMillis);
// 设置jwt的body
JwtBuilder builder = Jwts.builder()
// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
.setClaims(claims)
// 设置签名使用的签名算法和签名使用的秘钥
.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
// 设置过期时间
.setExpiration(exp);
return builder.compact();
}
接下来是一个固定的格式使用builder中的setClaims或者addClaims添加信息,使用signWith传入连个参数,第一个是设置签名算法,第二个是设置秘钥.然后是过期时间.最后调用compact方法用于将builder转换成一个紧凑的字符串
解析jwt令牌
public static Claims parseJWT(String secretKey, String token) {
// 得到DefaultJwtParser
Claims claims = Jwts.parser()
// 设置签名的秘钥
.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
// 设置需要解析的jwt
.parseClaimsJws(token).getBody();
return claims;
}
传入秘钥和令牌就可以获得信息.
在苍穹外卖里整体流程是这样的
首先将一些固定信息定义在application.yml里
sky:
jwt:
# 设置jwt签名加密时使用的秘钥
admin-secret-key: itcast
# 设置jwt过期时间
admin-ttl: 7200000
# 设置前端传递过来的令牌名称
admin-token-name: token
然后定义一个Jwtproperties类
@Component
@ConfigurationProperties(prefix = "sky.jwt")
@Data
public class JwtProperties {
/**
* 管理端员工生成jwt令牌相关配置
*/
private String adminSecretKey;
private long adminTtl;
private String adminTokenName;
}
@ConfigurationProperties(prefix = "sky.jwt")使用这个注解自动映射要注意变量名得是属性名去掉了"-"后的驼峰命名.
然后创建并使用
@Autowired private JwtProperties jwtProperties;
String token = JwtUtil.createJWT(
jwtProperties.getAdminSecretKey(),
jwtProperties.getAdminTtl(),
claims);