当前位置: 首页 > 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两款流行工具的优势与不足,并提出结论和建议。 开发研发视角:蓝湖 优点: 清晰的设计规范:蓝湖为开发工程师提供了清晰的设计…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...