JWT(JSON Web Token)是一种用于在网络应用中安全地传递声明信息的开放标准(RFC 7519)。就像上班用的工牌一样,员工入职办理一张工牌,以后每次去公司都要刷工牌才能进。
格式是由大小写字母、下划线和数字组成的串,中间由两个“.”分割成三部分:
- Header(头部):通常包含令牌的类型(如
JWT
)和所使用的加密算法(如HS256
、RS256
等)。 - Payload(有效载荷):包含声明,比如用户身份、权限、过期时间等信息。
- Signature(签名):用于验证消息的完整性和真实性,防止数据被篡改。
Header、Payload都是由base64加密处理后放入jwt前两部分中,Signature是由Header和Payload加密之后拼接到一起再加盐加密,放入jwt第三不放呢。
实战
引入JWT依赖
首先引入pom相关依赖,版本与自己项目的java版本相匹配。
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
编写JWT生成和解析方法
新建单元测试类,在测试类中创建生成jwt和解析jwt方法。
在生成方法中,可以设置jwt的header、payload、signature三部分的参数,其中的加密算法,过期时间可灵活选择,签名(密钥)是保证jwt安全性的重要保障,可设置成特定值。
生成和解析方法中分别使用Jwts中的builder()和parse()方法来生成和解析jwt。
在解析jwt之后,可以通过已封装结果的get方法获得用户的各种信息(id、name、过期时间等)。
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.UUID;
@Slf4j
public class Test {
private long time = 1000*60*60*24;
private String signature = "admin";
@org.junit.Test
public void jwt(){
JwtBuilder jwtBuilder = Jwts.builder();
String jwtToken = jwtBuilder
//设置JWT头,类型 JWT;加密算法 哈希256
.setHeaderParam("type","JWT")
.setHeaderParam("alg","HS256")
//设置payload
.claim("user", "tom")
.claim("role", "admin")
.setSubject("admin-test")
.setExpiration(new Date(System.currentTimeMillis()+time))
.setId(UUID.randomUUID().toString())
//设置签名
.signWith(SignatureAlgorithm.HS256, signature)
.compact();
System.out.println(jwtToken);
}
@org.junit.Test
public void parse(){
String token = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJ1c2VyIjoidG9tIiwicm9sZSI6ImFkbWluIiwic3ViIjoiYWRtaW4tdGVzdCIsImV4cCI6MTcyMzY3MzE3MiwianRpIjoiZjUxMWFmZTItMWY1Ny00ZDRlLWFmZWYtOTg5NDg4YWRjMzU4In0.Kqsyxsxcec_2aMmbWTcBnASHkArVQ1EGI_b51640RSk";
JwtParser jwtParser = Jwts.parser();
Claims claims = jwtParser.setSigningKey(signature).parseClaimsJws(token).getBody();
log.info(claims.getId());
log.info((String) claims.get("user"));
log.info(claims.getSubject());
log.info(String.valueOf(claims.getExpiration()));
}
}
以上就是JWT令牌在项目中的简单使用,若想在大型项目中进一步解耦,可以抽象出配置类和常量类,将密钥(签名)、过期时间写入配置类,将参数类型定义成枚举字段。
参考资料:
【【极简入门】15分钟学会JWT的使用】 https://www.bilibili.com/video/BV1cK4y197EM/?share_source=copy_web&vd_source=b801836c05e38cbd2348169f8f2b95f5