package com.boot.utils;
import com.boot.constant.TokenConstant;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* JWT工具类
* 内置access_token和refresh_token可实现JWT token的无状态续签
* @author youzhengjie 2022-09-21 20服务器托管网:56:56
*/
@Slf4j
public class JwtUtil {
private static final String ACCESS_SECRET="security-jwt-accesstoken";//access_token密钥
private static final String REFRESH_SECRET="security-jwt-refreshtoken";//refresh_token密钥
//access_token过期时间 60*1000*60L=60分钟过期
private static final Long ACCESS_TOKEN_EXPIRATION=60 *1000 * 60L;
//refresh_token过期时间 60*1000*180L=180分钟过期
private static final Long REFRESH_TOKEN_EXPIRATION=60 *1000 * 180L;
/**
*
* @return 随机的uuid
*/
public static String getUUID(){
String token = UUID.randomUUID().toString().replaceAll("-", "");
return token;
}
/**
* @return 同时返回access_token和refresh_token的map集合
* 通过map集合.get(TokenConstant.ACCESSTOKEN)可以拿到access token
* 通过map集合.get(TokenConstant.REFRESHTOKEN)可以拿到refresh token
*/
public static MapString,String> createAccessTokenAndRefreshToken(String subject){
MapString,String> tokenMap=new ConcurrentHashMap>();
String accessToken = createAccessToken(subject);
String refreshToken = createRefreshToken(subject);
tokenMap.put(TokenConstant.ACCESSTOKEN,accessToken);
tokenMap.put(TokenConstant.REFRESHTOKEN,refreshToken);
return tokenMap;
}
/**
* 根据用户id生成access_token
* @param subject 例如userid
* @return 返回access token
*/
public static String createAccessToken(String subject){
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
long expMillis = nowMillis + ACCESS_TOKEN_EXPIRATION; //access_token过期时间
return Jwts.builder()
.setId(getUUID()) //唯一的ID
.setSubject(subject) //数据内容就存放到这里
.setIssuer("youzhengjie") // 签发者
.setIssuedAt(now) // 颁发token时间
.setExpiration(new Date(expMillis))//token过期时间
.signWith(SignatureAlgorithm.HS256,ACCESS_SECRET)
.compact();
}
/**
* 下面的代码已经自带了校验签名和过期时间,如果签名不正确或者过期了则直接会抛出异常
* @param accessToken 解析access_token
* @return
*/
public static Claims parseAccessToken(String accessToken) {
Claims claims = null;
try {
claims = Jwts.parser().setSigningKey(ACCESS_SECRET)
.parseClaimsJws(accessToken)
.getBody();
} catch (Exception ex) {
ex.printStackTrace();
}
return claims;
}
/**
* 根据用户id生成refresh_token
* @param subject 例如userid
* @return 返回refresh token
*/
public static String createRefreshToken(String subject){
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
long expMillis = nowMillis + REFRESH_TOKEN_EXPIRATION; //refresh_token过期时间
return Jwts.builder()
.setId(getUUID()) //唯一的ID
.setSubject(subject) //数据内容就存放到这里
.setIssuer("youzhengjie") // 签发者
.setIssuedAt(now) // 颁发token时间
.setExpiration(new Date(expMillis))//token过期时间
.signWith(Signa服务器托管网tureAlgorithm.HS256,REFRESH_SECRET)
.compact();
}
/**
* 下面的代码已经自带了校验签名和过期时间,如果签名不正确或者过期了则直接会抛出异常
* @param refreshToken 解析refresh_token
* @return 如果refreshToken过期了则返回null
*/
public static Claims parseRefreshToken(String refreshToken) {
Claims claims = null;
try {
claims = Jwts.parser().setSigningKey(REFRESH_SECRET)
.parseClaimsJws(refreshToken)
.getBody();
} catch (Exception ex) {
ex.printStackTrace();
}
return claims;
}
/**
* 判断token是否可以被刷新(主要就是看refresh_token是否过期,如果没有过期则可以刷新token)
* @param refreshToken
* @return true就是refreshtoken可以使用,反之则不行
*/
public static boolean canRefresh(String refreshToken){
Claims claims = parseRefreshToken(refreshToken);
return !isRefreshTokenExpired(claims);
}
/**
* 去刷新token,本质上就是重新生成新的accesstoken和refreshtoken并替代掉前端localstorage的旧的accesstoken和refreshtoken
* @param refreshToken
* @return 如果不能刷新token,则返回null
*/
public static MapString, String> toRefreshToken(String refreshToken){
//先判断refreshToken是否过期,看看能不能刷新token,否则返回null
if(!canRefresh(refreshToken)){
return null;
}
Claims claims = parseRefreshToken(refreshToken);
String subject = claims.getSubject();
return createAccessTokenAndRefreshToken(subject);//重新生成accesstoken和refreshtoken
}
/**
* 判断access_token是否过期
* @param claims
* @return true就是过期了
*/
public static boolean isAccessTokenExpired(Claims claims) {
Date expiredDate = claims.getExpiration();
return expiredDate.before(new Date()); //expiredDate
}
/**
* 判断refresh_token是否过期
* @param claims
* @return true就是过期了
*/
public static boolean isRefreshTokenExpired(Claims claims) {
Date expiredDate = claims.getExpiration();
return expiredDate.before(new Date()); //expiredDate
}
/**
* 测试util
* @param args
*/
public static void main(String[] args) {
String userid="123123999777";
//1: 生成token
MapString, String> tokenMap = createAccessTokenAndRefreshToken(userid);
String accesstoken = tokenMap.get(TokenConstant.ACCESSTOKEN);
String refreshtoken = tokenMap.get(TokenConstant.REFRESHTOKEN);
log.warn(accesstoken);
log.warn(refreshtoken);
//2:解析token
Claims c1 = parseAccessToken(accesstoken);
Claims c2 = parseRefreshToken(refreshtoken);
String s1 = c1.getSubject();
System.out.println(s1);
String s2 = c2.getSubject();
System.out.println(s2);
//3:刷新token
MapString, String> refreshTokenMap = toRefreshToken(refreshtoken);
String accesstoken2 = refreshTokenMap.get(TokenConstant.ACCESSTOKEN);
String refreshtoken2 = refreshTokenMap.get(TokenConstant.REFRESHTOKEN);
log.warn("------------------");
log.warn(accesstoken2);
log.warn(refreshtoken2);
Claims claims1 = parseAccessToken(accesstoken2);
Claims claims2 = parseRefreshToken(refreshtoken2);
System.out.println(claims1.getSubject());
System.out.println(claims2.getSubject());
}
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
1.DriverManager加载数据库驱动 2.Connection服务器托管网获得数据库连接 3.Statement获得执行SQL语句的PreparedStatuement或者Statement处理ResultSet结果集 参考文档: https://ww…