当前位置: 首页 > news >正文

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("未获取到用户信息");}
}

相关文章:

JAVA简单封装UserUtil

目录 思路 一、TokenFilterConfiguration 二、FilterConfig 三、TokenContextHolder 四、TokenUtil 五、UserUtil 思路 配置Token过滤器(TokenFilterConfiguration)&#xff1a;实现一个Token过滤器配置&#xff0c;用于拦截HTTP请求&#xff0c;从请求头中提取Token&…...

【TOOLS】Chrome扩展开发

Chrome Extension Development 1. 入门教程 入门案例&#xff0c;可以访问【 谷歌插件官网官方文档 】查看官方入门教程&#xff0c;这里主要讲解大概步骤 Chrome Extenson 没有固定的脚手架&#xff0c;所以项目的搭建需要根据开发者自己根据需求搭建项目&#xff08;例如通过…...

分享WPF的UI开源库

文章目录 前言一、HandyControl二、AduSkin三、Adonis UI四、Panuon.WPF.UI五、LayUI-WPF六、MahApps.Metro七、MaterialDesignInXamlToolkit八、FluentWPF九、DMSkin总结 前言 分享WPF的UI开源库。 一、HandyControl HandyControl是一套WPF控件库&#xff0c;它几乎重写了所…...

[ACM独立出版]2024年虚拟现实、图像和信号处理国际学术会议(ICVISP 2024)

最新消息ICVISP 2024-已通过ACM出版申请投稿免费参会&#xff0c;口头汇报或海报展示(可获得相应证明证书) ————————————————————————————————————————— [ACM独立出版]2024年虚拟现实、图像和信号处理国际学术会议&#xff08;ICVI…...

JVM:类加载器

文章目录 一、什么是类加载器二、类加载器的应用场景三、类加载器的分类1、分类2、启动类加载器3、Java中的默认类加载器&#xff08;1&#xff09;扩展类加载器&#xff08;2&#xff09;应用程序类加载器&#xff08;3&#xff09;arthas中类加载器相关的功能 四、双亲委派机…...

支持向量机 (support vector machine,SVM)

支持向量机 &#xff08;support vector machine&#xff0c;SVM&#xff09; flyfish 支持向量机是一种用于分类和回归的机器学习模型。在分类任务中&#xff0c;SVM试图找到一个最佳的分隔超平面&#xff0c;使得不同类别的数据点在空间中被尽可能宽的间隔分开。 超平面方…...

宝塔面板以www用户运行composer

方式一 执行命令时指定www用户 sudo -u www composer update方式二 在网站配置中的composer选项卡中选择配置运行...

昇思25天打卡营-mindspore-ML- Day24-基于 MindSpore 实现 BERT 对话情绪识别

学习笔记&#xff1a;基于MindSpore实现BERT对话情绪识别 算法原理 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是由Google于2018年开发的一种预训练语言表示模型。BERT的核心原理是通过在大量文本上预训练深度双向表示&#xff0…...

【精品资料】模块化数据中心解决方案(33页PPT)

引言&#xff1a;模块化数据中心解决方案是一种创新的数据中心设计和部署策略&#xff0c;旨在提高数据中心的灵活性、可扩展性和效率。这种方案通过将数据中心的基础设施、计算、存储和网络资源封装到标准化的模块中&#xff0c;实现了快速部署、易于管理和高效运维的目标 方案…...

N6 word2vec文本分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊# 前言 前言 上周学习了训练word2vec模型&#xff0c;这周进行相关实战 1. 导入所需库和设备配置 import torch import torch.nn as nn import torchvision …...

excel、word、ppt 下载安装步骤整理

请按照我的步骤开始操作&#xff0c;注意以下截图红框标记处&#xff08;往往都是需要点击的地方&#xff09; 第一步&#xff1a;下载 首先进入office下载网址&#xff1a; otp.landian.vip 然后点击下载 拉到下方 下载站点&#xff08;这里根据自己的需要选择下载&#x…...

【python学习】标准库之日期和时间库定义、功能、使用场景和示例

引言 datetime模块最初是由 Alex Martelli 在 Python 2.3 版本引入的&#xff0c;目的是为了解决之前版本中处理日期和时间时存在的限制和不便 在datetime模块出现之前&#xff0c;Python 主要使用time模块来处理时间相关的功能&#xff0c;但 time模块主要基于 Unix 纪元时间&…...

Android --- Kotlin学习之路:基础语法学习笔记

------>可读可写变量 var name: String "Hello World";------>只读变量 val name: String "Hello World"------>类型推断 val name: String "Hello World" 可以写成 val name "Hello World"------>基本数据类型 1…...

嵌入式智能手表项目实现分享

简介 这是一个基于STM32F411CUE6和FreeRTOS和LVGL的低成本的超多功能的STM32智能手表~ 推荐 如果觉得这个手表的硬件难做,又想学习相关的东西,可以试下这个新出的开发板,功能和例程demo更多!FriPi炸鸡派STM32F411开发板: 【STM32开发板】 FryPi炸鸡派 - 嘉立创EDA开源硬件平…...

`nmap`模块是一个用于与Nmap安全扫描器交互的库

在Python中&#xff0c;nmap模块是一个用于与Nmap安全扫描器交互的库。Nmap&#xff08;Network Mapper&#xff09;是一个开源工具&#xff0c;用于发现网络上的设备和服务。虽然Python的nmap模块可能不是官方的Nmap库&#xff08;因为Nmap本身是用C/C编写的&#xff09;&…...

JVM系列 | 对象的创建与存储

JVM系列 | 对象的生命周期1 对象的创建与存储 文章目录 前言对象的创建过程内存空间的分配方式方式1 | 指针碰撞方式2 | 空闲列表 线程安全问题 | 避免空间冲突的方式方式1 | 同步处理&#xff08;加锁)方式2 | 本地线程分配缓存 对象的内存布局Part1 | 对象头Mark Word类型指针…...

【JavaScript 算法】快速排序:高效的排序算法

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、算法原理二、算法实现三、应用场景四、优化与扩展五、总结 快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;通过分治法将数组分为较小的子数组&#xff0c;递归地排序子数组。快速排序通常…...

Excel如何才能忽略隐藏行进行复制粘贴?

你有没有遇到这样的情况&#xff1a;数据很多&#xff0c;将一些数据隐藏后&#xff0c;进行复制粘贴&#xff0c;结果发现粘贴后的内容仍然将整个数据都显示出来了&#xff01;那么&#xff0c;Excel如何才能忽略隐藏行进行复制粘贴&#xff1f; 打开你的Excel表格 Excel如何…...

行人越界检测 越线 越界区域 多边形IOU越界判断

行人越界判断 越界判断方式&#xff1a;&#xff08;1&#xff09;bbox中心点越界&#xff08;或自定义&#xff09;&#xff08;2&#xff09;交并比IoU判断 越界类型&#xff1a;&#xff08;1&#xff09;越线 &#xff08;2&#xff09;越界区域 1.越线判断 bbox中心点xc、…...

「UCD」浅谈蓝湖Figma交互设计对齐

在现代数字产品的设计和开发过程中,选择合适的工具对于提高团队效率和保证产品质量至关重要。本文将从开发和设计两个不同的角度,探讨蓝湖和Figma两款流行工具的优势与不足,并提出结论和建议。 开发研发视角:蓝湖 优点: 清晰的设计规范:蓝湖为开发工程师提供了清晰的设计…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7

在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤&#xff1a; 第一步&#xff1a; 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为&#xff1a; // 改为 v…...