jjwt加密Token是现在后端比较流行的一种加密手段:本次教程采用的签名算法是HS256;
pom文件引入jjwt依赖:
<!-- jjwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
编写JjwtUtils工具类:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
//编写一个JwtUtil工具类,包含生成token和解析token方法。
public class JwtUtil {
/**
* 生成jwt
* 使用HS256算法,私钥使用固定密钥
* @param secretKey jwt密钥
* @param ttlMillis jwt过期时间
* @param claims 设置的信息
* @return
*/
public static String createJTW(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();
}
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;
}
}
在Yaml文件中配置token的相关信息:
//配置的Token相关属性信息
@Component
@ConfigurationProperties(prefix = "user.jwt")
@Data
public class JwtProperties {
private String userSecretKet;//解密密钥
private long userTtl;//过期时间
private String userTokenName;//token昵称
}
YAML文件中:
user:
jwt:
userSecretKet: user #解密密钥
user-ttl: 30000 #过期时间
user-token-name: token #token昵称
创建接收前端信息进行并封装的类:
UserThis:
import lombok.Data;
//假设现在前端传过来的信息,用UserThis类接收:
@Data
public class UserThis {
private Long id;
private String username;
private String name;
private String password;
public UserThis(Long id, String username, String password,String name) {
this.id = id;
this.username = username;
this.password = password;
this.name=name;
}
}
创建后端返回的信息给前端的相关类:
//假设后端要返回给前端的信息:::现在用UserVO封装
@Builder
@Data
public class UserVO {
private Long id;
private String userName;
private String name;
private String token;
}
常量类:
//定义的常量类,可根据个人喜好参考。或直接双引号:"赋值"。
public class JwtClaimsConstant {
public static final String USER_ID="userId";
public static final String USER_NAME="userName";
public static final String USERNAME="name";
public static final String USER_PASSWORD="password";
}
测试类:
注入token属性信息的配置类:yaml文件配置的类
@Autowired
private JwtProperties jwtProperties;
测试:
@org.junit.jupiter.api.Test
public void jwtTest(){
//假设现在前端传过来的信息,用UserThis类接收:
UserThis userThis = new UserThis(9L,"XIAOMING","12345678","小美");//假设:构造器的信息是前端传过来的信息
Map<String, Object>claims=new HashMap<>();//创建集合,存入用户信息
claims.put(JwtClaimsConstant.USER_ID,userThis.getId());//存入userId
claims.put(JwtClaimsConstant.USER_NAME,userThis.getUsername());//存入Username
claims.put(JwtClaimsConstant.USERNAME,userThis.getName());//存入Name
claims.put(JwtClaimsConstant.USER_PASSWORD,userThis.getPassword());//存入Password
// ==>> //调用JwtUtil工具类创建Token的方法.createJTW()
String token = JwtUtil.createJTW(
jwtProperties.getUserSecretKet(),//密钥名称
jwtProperties.getUserTtl(),//过期时间 ///密钥和时间都在yml文件里配置好了;直接注入并get
claims);//放入带载的信息集合claims对象
//假设后端要返回给前端的信息:::现在用UserVO封装
UserVO userVO=UserVO.builder() //.builder():需要在对应的实体类上加上注解@Builder才可以使用
.id(userThis.getId())//返回id
.userName(userThis.getUsername())//返回username
.name(userThis.getName())//返回name
.token(token)//返回token
.build();
System.out.println(userVO);//假设前端接收到的效果,直接打印输出。
///解析token,从token中拿到相关信息
Claims claimsVo=JwtUtil.parseJWT(
jwtProperties.getUserSecretKet(),
userVO.getToken());
//从token中拿到相关信息
Long userId=Long.valueOf(claimsVo.get(JwtClaimsConstant.USER_ID).toString()); //从token中拿到userId
String username=String.valueOf(claims.get(JwtClaimsConstant.USER_NAME).toString()); //从token中拿到username
String name=String.valueOf(claims.get(JwtClaimsConstant.USERNAME).toString()); //从token中拿到name
String password=String.valueOf(claims.get(JwtClaimsConstant.USER_PASSWORD)); //从token中拿到password
//***用当前线程存入userId
BaseContext.setCurrentId(userId);//用Thread存取userId
// BaseContext.setCurrentId(99L);//用Thread存取userId
System.out.println("---------------------------------------------------------");
System.out.println("拿到的用户Id是:"+userId);
System.out.println("拿到的用户username是:"+username);
System.out.println("拿到的用户name是:"+name);
System.out.println("拿到的用户password是:"+password);
//***从当前线程中取回userId
Long currentId = BaseContext.getCurrentId();
System.out.println("BaseContext从当前线程中取回的userId是:"+currentId);
BaseContext.removeCurrentId();
}
测试结果:
UserVO(id=9, userName=XIAOMING, name=小美, token=eyJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMzQ1Njc4IiwibmFtZSI6IuWwj-e-jiIsInVzZXJOYW1lIjoiWElBT01JTkciLCJleHAiOjE3MTg3MjAwMDksInVzZXJJZCI6OX0.QyS3PvNV0kB_WGHmguMxBhOjyZk87fT36aaPh7d2o9U)
---------------------------------------------------------
拿到的用户Id是:9
拿到的用户username是:XIAOMING
拿到的用户name是:小美
拿到的用户password是:12345678
BaseContext从当前线程中取回的userId是:9