JWT三种应用方式从Token获取登录id
1、定义JWT工具类
里面有个解析的方法
package com.qfedu.common.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;
/**
* jwt工具类
*/
public class JwtUtils {
// 密钥
private final static String secret = "123456789qwertyui";
/**
* 生成jwt
*
* @param claims
* @return
*/
public static String createJwt(Map<String, Object> claims) {
// 签名算法,表示sha256
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//构造jwt
JwtBuilder builder = Jwts.builder()//.setHeaderParam("type","jwt") // 设置头
.setClaims(claims) // 设置载荷
.setExpiration(new Date(System.currentTimeMillis() + 180000000)) // 设置过期时间
.signWith(signatureAlgorithm, secret); // 使用指定算法设置签名
//生成jwt
return builder.compact();
}
/**
* 解析,如果不符合,报异常
*
* @param jsonWebToken
* @return
*/
public static Claims parseJWT(String jsonWebToken) {
try {
Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(jsonWebToken).getBody();
return claims;
} catch (Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}
}
每次使用都需要调这个方法
// 从请求头里获取Token 这个key不固定需前端一样
String jwt = request.getHeader("Token");
Claims claims = JwtUtils.parseJWT(jwt);
Object uid = claims.get("uid");
以这个方法来说有点麻烦每次都需要获取头部token,再去解析
重点来了,为什么不去尝试直接再去写个工具类,直接解析好呢
直接展示代码
2、封装工具类
package com.qfedu.common.utils;
import io.jsonwebtoken.Claims;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* --- 天道酬勤 ---
*
* @author Xiaoze
* @date 2024/8/20
* @desc
*/
public class TokenUtils {
public static Integer getUidFromToken() {
// 动态获取 HttpServletRequest 对象
ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request= attributes.getRequest();
String token = request.getHeader("Token");
if(token == null || token.isEmpty()){
throw new RuntimeException("token不存在");
}
Claims claims = JwtUtils.parseJWT(token);
Object uid = claims.get("uid");
return Integer.valueOf(uid.toString());
}
}
最最最重要的一种方式来了,我这种方式是写在登录拦截器中没错没错就是你想的那种方案
将解析出来的id储存到ThreadLocal中
package com.qfedu.common.interceptor;
import com.qfedu.common.annotation.NoLoginCheck;
import com.qfedu.common.ec.NoLoginException;
import com.qfedu.common.utils.JwtUtils;
import com.qfedu.common.utils.UserUtils;
import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* --- 天道酬勤 ---
*
* @author Xiaoze
* @date 2024/8/19
* @desc 登录前置拦截器
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 判断访问的控制器的方法有没有使用指定的注解 (NoLoginCheck)
if(handler instanceof HandlerMethod){
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 判断方法是否使用了指定的注解
boolean ret = handlerMethod.hasMethodAnnotation(NoLoginCheck.class);
// 说明不需要进行登录状态的判断,直接放行
if(ret){
return true;
}
String token = request.getHeader("Token");
if(token == null || "".equals(token)){
throw new NoLoginException(50008,"无效令牌,请重新登录");
}
try {
Claims claims = JwtUtils.parseJWT(token);
Object uid = claims.get("uid");
UserUtils.setId(Integer.valueOf(uid.toString()));
} catch (Exception e) {
throw new NoLoginException(50008,"无效令牌,请重新登录");
}
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 删除用户id
UserUtils.removeId();
}
}
在定义一个工具类
package com.qfedu.common.utils;
/**
* --- 天道酬勤 ---
*
* @author Xiaoze
* @date 2024/8/20
* @desc 获取token uid第三种方式
*/
public class UserUtils {
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static void setId(Integer uid) {
threadLocal.set(uid);
}
public static Integer getId() {
return threadLocal.get();
}
public static void removeId() {
threadLocal.remove();
}
}
最后调用
Integer uid = UserUtils.getId();
虽然最后一种方法比前两种方法代码都多,但是这种在工作环境中属于比较装的方式,看不出自己是小白