JAVA简单封装UserUtil

目录

思路

一、TokenFilterConfiguration

二、FilterConfig

三、TokenContextHolder

四、TokenUtil

五、UserUtil


思路

  1. 配置Token过滤器(TokenFilterConfiguration):实现一个Token过滤器配置,用于拦截HTTP请求,从请求头中提取Token,并通过调用TokenUtil验证Token的有效性

    1. 无效:response响应401

    2. 有效:将Token值存储在ThreadLocal中

  2. 配置过滤器(FilterConfig):用于注册和统一管理所有自定义过滤器

  3. 配置Holder类(TokenContextHolder):利用ThreadLocal机制管理每个线程绑定的Token,确保在一个线程内的请求间Token的一致性和隔离性。

  4. 创建TokenUtil工具类:token为key获取redis中数据,调用TokenUtil中的方法调feign获取用户信息,验证token是否有效

  5. 创建UserUtil工具类:从TokenContextHolder中获取当前的token,用TokenUtil解析token,获取用户信息

一、TokenFilterConfiguration

Token隔离过滤器配置类,实现基于Bearer Token的权限验证

/*** Token隔离过滤器配置类,用于实现基于Bearer Token的权限验证。* 该类作为一个过滤器,拦截进入系统的HTTP请求,验证请求中携带的Token是否有效,* 从而决定是否允许请求继续传递到系统内部。*/
@Slf4j
@Configuration
public class TokenFilterConfiguration implements Filter {/*** 处理HTTP请求。* 验证请求中是否包含有效的Bearer Token,并在验证通过后将Token值存储在ThreadLocal中,* 以便后续的业务逻辑可以获取到当前请求的用户信息。** @param servletRequest    HTTP请求对象* @param servletResponse   HTTP响应对象* @param filterChain       过滤器链,用于继续处理或终止请求的传递* @throws IOException      如果在处理请求或响应时发生I/O错误* @throws ServletException 如果在处理请求或响应时发生Servlet相关错误*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;try {// 从请求头中提取Bearer Token// 检查是否已经登录String tokenValue = BearerTokenExtractorUtil.extract(request);log.info("过滤器获取到token:{}", tokenValue);// 如果Token存在,则验证Token的有效性if (StrUtil.isNotEmpty(tokenValue)) {// 验证是否有效SysUserDto tokenUser = getUserInfoFromSys(tokenValue);// 如果Token无效,则返回401未授权错误if (ObjectUtil.isEmpty(tokenUser)) {// 如果token无效,直接响应401给客户端并结束执行response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write("Unauthorized: token失效,未获取到用户登录信息,请重新登录");return;}// Token有效,将Token值存储在ThreadLocal中,以便后续使用// 有效登录的情况,把请求头中的token设置进上下文TokenContextHolder.setToken(tokenValue);log.info("将请求头中的token设置进上下文context");}} catch (Exception e) {// 记录Token验证过程中的异常// 统一异常处理log.error("获取用户信息异常:", e);// 抛出未授权异常,提示客户端重新登录throw new UnauthorizedException("登录状态异常,请重新登录");}// 所有前置检查通过后,继续执行过滤器链filterChain.doFilter(servletRequest, servletResponse);// 请求处理完成后,清除ThreadLocal中的Token值TokenContextHolder.clear();}
}

二、FilterConfig

注册和管理过滤器

/*** 配置类,用于注册和管理过滤器。*/
@Configuration
public class FilterConfig {/*** 注册认证过滤器。* 创建一个FilterRegistrationBean实例,用于配置和注册自定义的TokenFilter。* 通过设置过滤器适用的URL模式,确保只有指定的API请求才会经过该过滤器进行认证检查。** @return FilterRegistrationBean 对象,用于注册过滤器并配置其属性。*/@Beanpublic FilterRegistrationBean authenticationFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new TokenFilterConfiguration());registration.addUrlPatterns("/api/*","/flow/*");return registration;}
}

三、TokenContextHolder

管理线程绑定的token,提供线程安全的访问方式

/*** TokenContextHolder 类用于管理线程绑定的token,提供线程安全的访问方式。* 利用ThreadLocal实现线程之间的隔离,确保每个线程操作的token互不干扰。*/
public class TokenContextHolder {/*** 使用TransmittableThreadLocal来存储线程绑定的token。* TransmittableThreadLocal相比于普通的ThreadLocal,还支持在子线程中传递值,* 适用于需要跨线程传递上下文信息的场景。*//*** 支持父子线程之间的数据传递*/private static final ThreadLocal<String> CONTEXT = new TransmittableThreadLocal<>();/*** 设置当前线程的token。* * @param token 要设置的token值。*/public static void setToken(String token) {CONTEXT.set(token);}/*** 获取当前线程的token。* * @return 当前线程绑定的token值。*/public static String getToken() {return CONTEXT.get();}/*** 清除当前线程的token。* 该方法用于在不再需要token时,或者在处理完特定业务逻辑后,清除线程绑定的token,以避免潜在的安全问题。*/public static void clear() {CONTEXT.remove();}
}

四、TokenUtil

token工具类


@Slf4j
@Component
public class TokenUtil implements BeanFactoryAware {@Setterprivate static RedisTemplate<String, Object> redisTemplate;@Setterprivate static SysFlowableFeign sysFlowableFeign;private static final String FLOWABLE_TOKEN_KEY = "token_user:";/*** 设置BeanFactory,用于获取RedisTemplate和SysFlowableFeign实例。*/@Override@SuppressWarnings("unchecked")public void setBeanFactory(@NonNull BeanFactory beanFactory) throws BeansException {RedisTemplate<String, Object> redisBean = beanFactory.getBean("redisTemplate", RedisTemplate.class);setRedisTemplate(redisBean);SysFlowableFeign sysFlowableFeignBean = beanFactory.getBean(SysFlowableFeign.class);setSysFlowableFeign(sysFlowableFeignBean);}/*** 构建Token的键值。* * @param token 用户的Token字符串。* @return 构建后的Token键值。*/private static String getTokenKey(String token) {return  TOKEN_KEY + token;}/*** 根据Token获取用户信息。* * @param token 用户的Token字符串。* @return 用户信息的SysUserDto对象。* @throws UnauthorizedException 如果Token无效或过期,则抛出此异常。*/public static SysUserDto getTokenUser(String token) {try {String tokenKey = getTokenKey(token);// 缓存中获取SysUserDto redisUser = (SysUserDto) redisTemplate.opsForValue().get(tokenKey);if (ObjectUtil.isNotNull(redisUser)) {log.info("根据token获取缓存中的用户信息:{}", JSONUtil.toJsonStr(redisUser));return redisUser;}log.info("缓存中的用户信息已过期");// 缓存中未找到用户信息,从SYS验证token是否已过期SysUserDto userInfoFromSys = getUserInfoFromSys(token);if (ObjectUtil.isNull(userInfoFromSys)) {log.info("缓存中未找到用户信息,从SYS验证token已过期");// 未获取到用户信息throw new UnauthorizedException("Unauthorized: token失效,未获取到用户登录信息,请重新登录");}log.info("缓存中未找到用户信息,根据token获取SYS用户信息:{}", JSONUtil.toJsonStr(userInfoFromSys));// 存储到本地缓存redisTemplate.opsForValue().set(tokenKey, userInfoFromSys);// 设置缓存时间1天有效redisTemplate.expire(tokenKey, 1, TimeUnit.DAYS);return userInfoFromSys;} catch (Exception e) {// 统一异常处理log.error("获取用户信息异常:", e);throw new UnauthorizedException("登录状态异常,请重新登录");}}/*** feign获取用户信息* @param token 用户的Token字符串。* @return 用户信息的SysUserDto对象,如果获取失败则返回null。*/public static SysUserDto getUserInfoFromSys(String token) {ApiResult<SysUserDto> tokenUserResult = sysFlowableFeign.getTokenUser(token);if (BooleanUtil.isTrue(tokenUserResult.getSuccess())) {return tokenUserResult.getData();}return null;}}

五、UserUtil

用户工具类

/*** 用户工具类,提供获取当前登录用户的业务逻辑。*/
public class UserUtil {/*** 日志记录器,用于记录类的操作日志。*/private static final Logger log = LoggerFactory.getLogger(UserUtil.class);// 私有构造方法,防止外部实例化private UserUtil() {}/*** 获取当前登录的用户信息。** @return 当前登录用户的SysUserDto对象。* @throws UnauthorizedException 如果token失效或未获取到用户登录信息,抛出此异常。* @throws IllegalArgumentException 如果未从上下文中获取到token,抛出此异常。*/public static SysUserDto getCurrentUser() {// 从TokenContextHolder中获取当前的tokenString token = TokenContextHolder.getToken();log.info("获取上下文context中的token:{}", token);if (CharSequenceUtil.isNotEmpty(token)) {// 使用TokenUtil解析token,获取用户信息SysUserDto tokenUser = TokenUtil.getTokenUser(token);if (ObjectUtil.isEmpty(tokenUser)) {throw new UnauthorizedException("Unauthorized: token失效,未获取到用户登录信息,请重新登录");}// 返回解析得到的用户信息return tokenUser;}throw new IllegalArgumentException("未获取到用户信息");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/44639.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IDEA Plugins 网络异常解决办法

设置HTTP代理&#xff1a; 进入 File -> Settings -> Appearance & Behavior -> System Settings -> HTTP Proxy。勾选 “Auto-detect proxy setting” 或者手动设置代理&#xff0c;例如 http://127.0.0.1:1080 或 https://plugins.jetbrains.com。重启 IDEA…

【STM32学习】stm32cubemx基础配置,点亮/闪烁一个LED灯

1、cubemx开始 打开cubemx&#xff0c;在help栏中&#xff0c;点击&#xff0c;选择安装你所需要的stm32芯片版本&#xff0c; 打开后&#xff0c;选择你所配置的芯片型号&#xff0c;如我配置的是stm32f4系列&#xff0c;勾选&#xff0c;点击Install。 安装好后&#xff0c;…

HybridCLR原理中的重点总结

序言 该文章以一个新手的身份&#xff0c;讲一下自己学习的经过&#xff0c;大家更快的学习HrbirdCLR。 我之前的两个Unity项目中&#xff0c;都使用到了热更新功能&#xff0c;而热更新的技术栈都是用的HybridCLR。 第一个项目本身虽然已经集成好了热更逻辑&#xff08;使用…

Java | Leetcode Java题解之第227题基本计算器II

题目&#xff1a; 题解&#xff1a; class Solution {public int calculate(String s) {Deque<Integer> stack new ArrayDeque<Integer>();char preSign ;int num 0;int n s.length();for (int i 0; i < n; i) {if (Character.isDigit(s.charAt(i))) {num…

Elasticseach学习

概念 是一个开源的分布式搜索引擎&#xff0c;可以应用于搜索、日志监控等 倒排索引 正向索引&#xff1a;基于文档id创建索引。查询词条时必须先找到文档&#xff0c;而后判断是否包含词条 倒排索引&#xff1a;对文档内容分词&#xff0c;对词条创建索引&#xff0c;并记录…

docker-compose mongodb 副本集

准备 cd /opt/mongos 把 3 个节点的数据目录创建好 mkdir -p ./mongos/{mongo1,mongo2,mongo3} mongodb 使用 keyFile 进行认证&#xff0c;副本集群中的每个节点的 mongodb 使用 keyFile 的内容作为认证其他成员的共享密码。mongodb 实例只有拥有正确的 keyFile 才可以加入副…

Java中的设计模式:工厂模式

Java中的设计模式&#xff1a;工厂模式 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. 什么是工厂模式&#xff1f; 工厂模式是一种创建型设计模式&#xff0c;用于创建对象的过程被推迟到子类…

HCIP课堂笔记

第一章 1、数据转换---目标&#xff1a;抽象语言---二进制---电信号 2、应用程序---接收参数和指令&#xff08;编码&#xff1a;接收传递给计算机指令参数最终转换为二进制&#xff09; 3、二进制---电信号 4、对于整个互联网而言指定了统一的标准——OSI/RM参考模型 &…

GitLab和Git

GitLab保姆级教程 文章目录 GitLab保姆级教程一、GitLab安装二、添加组和用户三、新增项目四、Git上传项目说明五、命令行指引 根据以下说明从计算机中上传现有文件&#xff1a;六、创建与合并分支七、GitLab回滚到特定版本八、数据备份与恢复九、docker中创建gitlab GIT 常用命…

“金山-讯飞”杯2024年武汉理工大学程序设计竞赛 A. Mobiusp败走***(思维题-点双连通分量、连通性)

题目 思路来源 官方题解 题解 手玩发现&#xff0c;能换的话&#xff0c;当且仅当.和1在一个环里&#xff0c;而这就是点双连通分量 所以最优策略是先把.换到(x,y)的位置&#xff0c;然后判断.和1在不在一个环里 也就是&#xff1a; 1. 判断删掉1时&#xff0c;.和(x,y)联…

vue 搭建 pinia

文章目录 环境设置存储读取数据【 storeToRefs】借助storeToRefs将store中的数据转为ref对象&#xff0c;方便在模板中使用【getters】当state中的数据&#xff0c;需要经过处理后再使用时&#xff0c;可以使用getters配置【$subscribe】通过 store 的 $subscribe() 方法侦听 s…

科研绘图系列:R语言圆形柱状图(circular barplot)

介绍 圆形柱状图(circular barplot),又称为雷达图或蜘蛛网图(Spider Chart),是一种用来展示多变量数据的图表。这种图表使用一个圆形的网格,将数据变量分布在一个或多个从中心点向外延伸的轴上,每个轴代表一个变量,数据点在轴上的位置表示该变量的值。然后,将这些点…

SAP与易链SRM系统集成案例

一、项目环境 重庆润通控股&#xff08;集团&#xff09;有限公司成立于2007年&#xff0c;是一家集合汽柴油动力及终端、摩托车、储能电源、汽车零部件、金融服务等产业的多元化集团公司。现拥有员工超4000人&#xff0c;业务遍布全球80多个国家及地区&#xff0c;2021年营…

Mysql LIKE什么时候走索引,什么时候不走索引

在 MySQL 中&#xff0c;LIKE 查询是否走索引&#xff0c;主要取决于通配符的位置和使用的存储引擎。 使用索引的情况 前缀匹配&#xff1a; 当 LIKE 查询中的通配符出现在字符串的末尾时&#xff0c;查询可以利用索引。例如&#xff0c;LIKE abc% 。这种情况下&#xff0c;索…

文件加密软件谁好用丨2024文件加密软件TOP6推荐

在数字化时代&#xff0c;数据安全已成为企业和个人不可忽视的重要议题。随着数据泄露事件频发&#xff0c;文件加密软件成为了保护敏感信息的首选工具。 本文将为您推荐2024年度最值得信赖的六大文件加密软件&#xff0c;帮助您选择最适合自己需求的加密工具。 1. 域智盾 软…

东方博宜1626 - 暑假的旅游计划

问题描述 期末考试结束了&#xff0c;小华语文、数学、英语三门功课分别考了 x、y、z 分&#xff0c;小华的家长说&#xff0c;如果小华三门功课的平均分在90 分或者 90 分以上&#xff0c;那么就去北京旅游&#xff0c;如果在 90 分以下&#xff0c;那么就去南京玩。 请从键盘…

[linux] git push时需要输入user 和keyword

git clone的要是ssh链接&#xff01;&#xff01;&#xff01;&#xff01; 1、用户名和邮箱 git config --global user.name "name" git config --global user.email "email" 2、生成ssh key (ED25519) ssh-keygen -t ed25519 -C "<自定义内容&g…

手机容器化 安装docker

旧手机-基于Termux容器化 1、安装app 在手机上安装Termux或ZeroTermux&#xff08;Termux扩展&#xff09; 1.1 切换源 注&#xff1a;可以将termux进行换源&#xff0c;最好采用国内源&#xff0c;例如&#xff1a;清华源等 更新包列表和升级包&#xff08;可选&#xff0…

健康云足迹:在iCloud中珍藏您的个人健康检查记录

健康云足迹&#xff1a;在iCloud中珍藏您的个人健康检查记录 随着健康意识的提高&#xff0c;个人健康数据管理变得越来越重要。iCloud作为苹果公司提供的云服务&#xff0c;不仅能够同步您的联系人、日历和照片&#xff0c;还能成为您个人健康检查记录的安全港湾。本文将详细…

数智驱动丨zAIoT 连续落地军工、科研院所和机械制造场景,推动数智化转型升级...

引言 在这个万物互联的时代&#xff0c;科技的进步正以不可阻挡之势&#xff0c;深刻地影响并重塑我们的生产和生活方式。数智化转型升级在各个领域展现出强大的动力&#xff0c;已经成为推动社会向前发展的关键力量。 最近&#xff0c;云和恩墨自主研发的数据智能分析处理平台…