JWT token验证后,通过 ThreadLocal 进行传值

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: JWT token验证后,通过 ThreadLocal 进行传值

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);
    }

 

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6天前
|
存储 中间件 API
ThinkPHP 集成 jwt 技术 token 验证
本文介绍了在ThinkPHP框架中集成JWT技术进行token验证的流程,包括安装JWT扩展、创建Token服务类、编写中间件进行Token校验、配置路由中间件以及测试Token验证的步骤和代码示例。
ThinkPHP 集成 jwt 技术 token 验证
|
10天前
|
JSON 安全 数据安全/隐私保护
从0到1搭建权限管理系统系列三 .net8 JWT创建Token并使用
【9月更文挑战第22天】在.NET 8中,从零开始搭建权限管理系统并使用JWT(JSON Web Tokens)创建Token是关键步骤。JWT是一种开放标准(RFC 7519),用于安全传输信息,由头部、载荷和签名三部分组成。首先需安装`Microsoft.AspNetCore.Authentication.JwtBearer`包,并在`Program.cs`中配置JWT服务。接着,创建一个静态方法`GenerateToken`生成包含用户名和角色的Token。最后,在控制器中使用`[Authorize]`属性验证和解析Token,从而实现身份验证和授权功能。
|
2月前
【Azure APIM】在APIM中实现JWT验证不通过时跳转到Azure登录页面
【Azure APIM】在APIM中实现JWT验证不通过时跳转到Azure登录页面
|
2月前
|
API
【Azure Developer】记录一段验证AAD JWT Token时需要设置代理获取openid-configuration内容
【Azure Developer】记录一段验证AAD JWT Token时需要设置代理获取openid-configuration内容
|
2月前
|
JSON Java API
【Azure Developer】如何验证 Azure AD的JWT Token (JSON Web 令牌)?
【Azure Developer】如何验证 Azure AD的JWT Token (JSON Web 令牌)?
|
2月前
|
JSON 算法 API
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
|
2月前
|
存储 开发框架 JSON
ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token
ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token
|
2月前
|
SQL Java 测试技术
在Spring boot中 使用JWT和过滤器实现登录认证
在Spring boot中 使用JWT和过滤器实现登录认证
130 0
|
5月前
|
安全 数据安全/隐私保护
Springboot+Spring security +jwt认证+动态授权
Springboot+Spring security +jwt认证+动态授权
188 0
|
3月前
|
JSON 安全 Java
使用Spring Boot和JWT实现用户认证
使用Spring Boot和JWT实现用户认证
下一篇
无影云桌面