Spring Boot JWT 用户认证

JWT token验证后,通过 ThreadLocal 进行传值,在服务层直接使用 Threadlocal 获取当前用户,的Id、姓名,进行行为记录

定义一个用户实体类

package com.vipsoft.core.user.entity;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.io.Serializable;
import java.util.Date;

public class TokenEntity implements Serializable {

private String userId;

private String userName;

private String accessToken;

private String refreshToken;

private int expiry;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.sssZ", timezone = "GMT+8")
private Date expiryDate;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.sssZ", timezone = "GMT+8")
private Date createTime;

public String getUserId() {
return userId;
}

public void setUserId(String userId) {
this.userId = userId;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getAccessToken() {
return accessToken;
}

public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

public String getRefreshToken() {
return refreshToken;
}

public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}

public int getExpiry() {
return expiry;
}

public void setExpiry(int expiry) {
this.expiry = expiry;
}

public Date getExpiryDate() {
return expiryDate;
}

public void setExpiryDate(Date expiryDate) {
this.expiryDate = expiryDate;
}

public Date getCreateTime() {
return createTime;
}

public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}

SessionBase

package com.vipsoft.core.user.entity;

public class SessionBase {

/**
* 用来存放登录用户的信息
*/
public static final ThreadLocal<TokenEntity> CURRENT_MEMBER = new ThreadLocal();

}

AuthorizationInterceptor

package com.vipsoft.web.boot.interceptor;


import cn.hutool.core.util.StrUtil;
import com.vipsoft.core.user.entity.SessionBase;
import com.vipsoft.core.user.entity.TokenEntity;
import com.vipsoft.web.boot.annotation.JwtIgnore;
import com.vipsoft.web.boot.exception.CustomException;
import com.vipsoft.web.boot.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Component
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
private Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private JwtUtils jwtUtils;


public static final String USER_KEY = "userId";

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//
// 忽略带JwtIgnore注解的请求, 不做后续token认证校验
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
JwtIgnore jwtIgnore = handlerMethod.getMethodAnnotation(JwtIgnore.class);
if (jwtIgnore != null) {
return true;
}
}

if (HttpMethod.OPTIONS.equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return true;
}

//获取用户凭证
String token = request.getHeader(jwtUtils.getHeader());
if (StrUtil.isBlank(token)) {
token = request.getParameter(jwtUtils.getHeader());
}

//凭证为空
if (StrUtil.isBlank(token)) {
throw new CustomException(HttpStatus.UNAUTHORIZED.value(), "token 不能为空");
}

Claims claims = jwtUtils.getClaimByToken(token);
if (claims == null || jwtUtils.isTokenExpired(claims.getExpiration())) {
throw new CustomException(HttpStatus.UNAUTHORIZED.value(), "token 失效,请重新登录");
}


String[] userinfo = claims.getSubject().split("\\|");
//判断redis是否存在这个key
// String redisKey = StrUtil.indexedFormat("TOKEN_USER", userinfo[0]);
// String redisValue = redisTemplate.opsForValue().get(redisKey);
// if (!token.equals(redisValue)) {
// throw new CustomException(HttpStatus.UNAUTHORIZED.value(), "token 失效,请重新登录");
// }

//新增ThreadLocal返回用户信息的方式
TokenEntity tokenEntity = new TokenEntity();
tokenEntity.setUserId(userinfo[0]);
tokenEntity.setUserName(userinfo[1]);
tokenEntity.setAccessToken(token);
SessionBase.CURRENT_MEMBER.set(tokenEntity);

//也可以通过 Request 数据传送,设置userId到request里,后续根据userId,获取用户信息
request.setAttribute(USER_KEY, userinfo[0]);
return true;
}
}

调用

@Override
public void insert(Users user) {
TokenEntity tokenEntity = SessionBase.CURRENT_MEMBER.get();
String userId = tokenEntity != null ? tokenEntity.getUserId() : "";
String userName = tokenEntity != null ? tokenEntity.getUserName() : "";
user.setCreateUserId(userId);
user.setCreateUserName(userName);
userMapper.insert(user);
}