我们知道 jwt(JSON Web Token)是基于RFC 7519标准的方法,并不是某公司的开源项目,所以jwt在java端有很多的实现库,主流的有jjwt、java-jwt、JOSE4j等,其实基础功能都差不多。本文提供的是基于 java-jwt 的工具类。
1. 依赖
<!-- jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
2. JwtUtils
public class JwtUtils {
//通过有效时间
private static int days = 7;
//密钥(需要后端严密保存)
private static String SecretKey = "852@$%#123!";
/**
* 生成token header.payload.sing
*/
public static String getToken(Map<String,String> map){
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE,days);
//创建jwt builder
JWTCreator.Builder builder = JWT.create();
//payload
map.forEach((k,v)->{
builder.withClaim(k,v);
});
//生成token,头部默认jwt和Base64编码
String token = builder.withExpiresAt(instance.getTime()) //设置过期时间
.sign(Algorithm.HMAC256(SecretKey)); //加密算法和密钥
return token;
}
/**
* 验证 token 合法性
*/
public static DecodedJWT verify(String token){
return JWT.require(Algorithm.HMAC256(SecretKey)).build().verify(token);
}
}
3. 使用生成
//仅为示例,可以以此扩展
@PostMaping("/login")
public String login(String username, String pwd){
//普通用户类
User user = new User(username,pwd);
userService.save(user); //mybatis plus
Map<String,String> map = new HashMap<>();
//请勿放用户的敏感信息,例如密码等
map.put("userId",user.getId());
map.put("username",user.getName());
String token = JwtUtils.getToken(map);
return token; //前端可以存入localStorage或是缓存中
}
4. 后端校验与获取
//一般在过滤器/拦截器中对请求拦截,从请求头中拿到该token。
try{
DecodedJWT jwt = JwtUtils.verify(token);
int userId = jwt.getClaim("userId").asInt();
Stirng username = jwt.getClaim("username").asString();
//自己的业务处理
//......
}catch(Exception e){
//自己的业务处理,或者直接抛出自定义异常
//.....
}
//如果token有任何问题,无论是过期、无效、非法等,该方法都会抛出相应的异常
//但是前端无需知道是哪种,因为结果都是让用户重新登录,所以不用过细的捕获
//直接返回统一的 请重新登录 即可。
工具类设计的相对简单,因为每个人向payload种放置的信息不同,所以本方法就直接把验证后的对象直接返回了,大家还可以自己向工具类中根据业务需求自己补充方法。