SpringBoot中基于 OAuth2 + Spring Security 的用户认证上下文工具库(UC Token Util)Starter 实践
SpringBoot中基于 OAuth2 Spring Security 的用户认证上下文工具库UC Token UtilStarter 实践一、涉及的技术知识点1.1 OAuth2 JWT 认证体系知识点说明OAuth2 协议标准的授权框架支持 password/client_credentials/refresh_token 等授权模式JWTJSON Web Token自包含令牌payload 中携带用户信息无需服务端查库验证Access Token / Refresh Token短效访问令牌 长效刷新令牌平衡安全性与用户体验Token 扩展字段additional_infoJWT payload 中自定义的业务字段memberId、userId 等RSA 非对称签名认证中心用私钥签名各微服务用公钥验签无需共享密钥1.2 Spring Security OAuth2知识点说明SecurityContextHolder持有当前线程的安全上下文Authentication 对象OAuth2AuthenticationDetailsOAuth2 认证详情包含 token 值和解码后的信息TokenStoreToken 存储接口支持从 Token 中读取 AuthenticationAuthentication.getDetails()获取认证附加信息additional_info map1.3 Spring Boot 自动配置知识点说明spring.factories自动配置入口声明ApplicationContextAware获取 Spring 容器上下文读取 Environment 配置Environment.getProperty()从配置文件中动态读取属性静态方法 Spring Bean通过ApplicationContextAware将 Spring 上下文注入到静态字段支持静态工具方法1.4 Token 解码技术知识点说明com.auth0.jwt.JWT.decode()解析 JWT 不验签仅读取 payload用于刷新 token 场景DecodedJWT.getClaim()从解码后的 JWT 中按 key 获取自定义 claimOAuth2AuthenticationDetails.getDecodedDetails()Spring Security 框架已解码的 Token 详情1.5 设计模式模式应用工具类模式UcTokenUtil提供静态方法无需实例化即可获取当前用户信息模板方法DefaultGenAccessTokenBody.getRequestBody()定义生成 Token 的模板子类可覆写loadAdditional/loadUserRoles策略模式不同场景target-token、gen-token、refresh-token走不同的认证中心接口外观模式对外只暴露getMemberId()、getUserId()等简单方法屏蔽底层 Security 复杂性注博客https://blog.csdn.net/badao_liumang_qizhi二、封装 Starter 的流程2.1 项目结构example-uc-token-starter/ ├── pom.xml └── src/main/ ├── java/com/example/uc/ │ ├── UcTokenUtil.java // 核心工具类对外API │ ├── autoconfigure/ │ │ └── UcTokenUtilAutoConfiguration.java // 自动配置 │ ├── config/ │ │ └── UcHeaderInterceptor.java // HTTP请求头拦截器 │ ├── dto/ │ │ ├── UcAccessTokenResult.java // 认证中心响应 │ │ ├── GenTokenParamDto.java // 生成Token入参 │ │ └── TargetTokenParamDto.java // 跳转Token入参 │ ├── enums/ │ │ └── TokenExtensionEnums.java // Token扩展字段枚举 │ └── role/ │ └── DefaultGenAccessTokenBody.java // Token生成模板可扩展 └── resources/META-INF/ └── spring.factories2.2 核心设计思路读取当前用户信息— 从 Spring Security Context 中获取已验证的 Token解析 additional_info服务间 Token 获取— 提供 targetAccessToken / genAccessToken / refreshAccessToken 方法用于后端服务之间的认证配置外置— 认证中心地址、clientId、clientPassword 通过 application.yml 配置零侵入— 引入依赖后自动注册 Bean业务代码直接调用静态方法三、通用示例代码3.1 spring.factories# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.example.uc.autoconfigure.UcTokenUtilAutoConfiguration3.2 UcTokenUtilAutoConfiguration自动配置packagecom.example.uc.autoconfigure;importcom.example.uc.UcTokenUtil;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;/** * UC Token工具自动配置类. */ConfigurationpublicclassUcTokenUtilAutoConfiguration{BeanpublicUcTokenUtilucTokenUtil(){returnnewUcTokenUtil();}}3.3 TokenExtensionEnumsToken 扩展字段枚举packagecom.example.uc.enums;/** * JWT Token中自定义扩展字段枚举. * 对应认证中心签发Token时写入的additional_info. */publicenumTokenExtensionEnums{USER_ID(user_id,用户ID),NAME(user_name_cn,用户名称),MEMBER_ID(member_id,会员ID),ACCOUNT_ID(uc_account_id,UC账户ID),AVATAR_ADDRESS(avatar_address,头像地址),POSITION_ID(position_id,岗位ID),PLATFORM_FROM(platform_from,来源平台),PLATFORM_TO(platform_to,目标平台);privatefinalStringkey;privatefinalStringdesc;TokenExtensionEnums(Stringkey,Stringdesc){this.keykey;this.descdesc;}publicStringgetKey(){returnkey;}publicStringgetDesc(){returndesc;}}3.4 UcTokenUtil核心工具类packagecom.example.uc;importcom.example.uc.enums.TokenExtensionEnums;importjava.util.Collections;importjava.util.Map;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.context.ApplicationContext;importorg.springframework.context.ApplicationContextAware;importorg.springframework.core.env.Environment;importorg.springframework.security.core.Authentication;importorg.springframework.security.core.context.SecurityContextHolder;importorg.springframework.security.oauth2.provider.OAuth2Authentication;importorg.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;importorg.springframework.security.oauth2.provider.token.TokenStore;importorg.springframework.util.Assert;importorg.springframework.util.StringUtils;/** * 用户认证上下文工具类. * 从当前请求的JWT Token中提取用户信息. * 需配合Spring Security OAuth2资源服务器使用. */publicclassUcTokenUtilimplementsApplicationContextAware{privatestaticfinalLoggerlogLoggerFactory.getLogger(UcTokenUtil.class);privatestaticStringauthCenterUrl;privatestaticStringclientId;privatestaticStringclientPassword;privatestaticApplicationContextcontext;OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext){contextapplicationContext;Environmentenvcontext.getEnvironment();authCenterUrlenv.getProperty(app.uc.auth-center.url,);clientIdenv.getProperty(app.uc.client-id,);clientPasswordenv.getProperty(app.uc.client-password,);}// 对外静态 API /** * 获取当前登录用户的会员ID. */publicstaticIntegergetMemberId(){returngetIntegerField(TokenExtensionEnums.MEMBER_ID);}/** * 获取当前登录用户的用户ID. */publicstaticIntegergetUserId(){returngetIntegerField(TokenExtensionEnums.USER_ID);}/** * 获取当前登录用户的UC账户ID. */publicstaticIntegergetUcAccountId(){returngetIntegerField(TokenExtensionEnums.ACCOUNT_ID);}/** * 获取当前登录用户的名称. */publicstaticStringgetName(){returngetStringField(TokenExtensionEnums.NAME);}/** * 获取当前登录用户的来源平台. */publicstaticStringgetPlatformFrom(){returngetStringField(TokenExtensionEnums.PLATFORM_FROM);}/** * 获取Token中任意扩展字段. */publicstaticObjectgetAdditionalInfo(Stringkey){returngetAdditionalInfoMap().get(key);}// 内部实现 privatestaticIntegergetIntegerField(TokenExtensionEnumsfield){ObjectvaluegetAdditionalInfoMap().get(field.getKey());if(value!null){returnInteger.valueOf(value.toString());}returnnull;}privatestaticStringgetStringField(TokenExtensionEnumsfield){ObjectvaluegetAdditionalInfoMap().get(field.getKey());returnvalue!null?value.toString():null;}/** * 从Spring Security上下文获取Token的additional_info. * * 解析流程: * 1. SecurityContextHolder获取当前Authentication * 2. 判断details类型: * - OAuth2AuthenticationDetails: 标准OAuth2流程从decodedDetails获取 * - HashMap: 内部服务调用传递的上下文信息 * 3. 如果decodedDetails为空通过TokenStore重新解析Token */privatestaticMapString,ObjectgetAdditionalInfoMap(){Assert.notNull(context,请配置为Spring Bean);AuthenticationauthenticationSecurityContextHolder.getContext().getAuthentication();if(StringUtils.isEmpty(authentication)){log.debug(当前认证信息为空);returnCollections.emptyMap();}Objectdetailsauthentication.getDetails();MapString,ObjectadditionalInfoCollections.emptyMap();if(detailsinstanceofOAuth2AuthenticationDetails){// 标准OAuth2请求从已解码的Token详情中获取OAuth2AuthenticationDetailsoAuth2Details(OAuth2AuthenticationDetails)details;if(oAuth2Details.getDecodedDetails()!null){return(MapString,Object)oAuth2Details.getDecodedDetails();}// 降级方案通过TokenStore重新读取TokenStoretokenStorecontext.getBean(TokenStore.class);OAuth2AuthenticationoAuth2AuthenticationtokenStore.readAuthentication(oAuth2Details.getTokenValue());additionalInfo(MapString,Object)oAuth2Authentication.getDetails();}elseif(detailsinstanceofjava.util.HashMap){// 内部Feign调用传递的上下文MapadditionalInfo(MapString,Object)details;}log.trace(Token扩展信息: {},additionalInfo);returnadditionalInfo;}}3.5 DefaultGenAccessTokenBodyToken 生成模板packagecom.example.uc.role;importcom.example.uc.dto.GenTokenParamDto;importjava.util.Collections;importjava.util.Map;importjava.util.Set;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;/** * Token生成请求体模板. * 子类可覆写loadAdditional/loadUserRoles实现自定义Token内容. */publicclassDefaultGenAccessTokenBody{privatestaticfinalLoggerlogLoggerFactory.getLogger(DefaultGenAccessTokenBody.class);/** * 组装生成Token的请求参数. * 模板方法固定流程子类可扩展additional和roles. */publicfinalGenTokenParamDtogetRequestBody(StringclientId,StringclientPassword,IntegerucAccountId,StringplatformFrom){GenTokenParamDtoparamDtonewGenTokenParamDto();paramDto.setClientId(clientId);paramDto.setClientPassword(clientPassword);paramDto.setUcAccountId(ucAccountId);paramDto.setAdditional(loadAdditional(ucAccountId));paramDto.setRoles(loadUserRoles(ucAccountId));returnparamDto;}/** * 加载Token附加信息子类可覆写. * 例如从数据库查询用户所属会员ID、头像等信息写入Token. */protectedMapString,StringloadAdditional(IntegerucAccountId){returnCollections.emptyMap();}/** * 加载用户角色集合子类可覆写. * 例如从数据库查询用户角色列表写入Token. */protectedSetStringloadUserRoles(IntegerucAccountId){returnCollections.emptySet();}}3.6 pom.xmlStarter 侧projectgroupIdcom.example/groupIdartifactIdexample-uc-token-starter/artifactIdversion1.0.0/versionpackagingjar/packagingdependenciesdependencygroupIdorg.springframework.security.oauth/groupIdartifactIdspring-security-oauth2/artifactIdscopeprovided/scope/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactIdscopeprovided/scope/dependencydependencygroupIdcom.auth0/groupIdartifactIdjava-jwt/artifactIdversion3.18.2/version/dependencydependencygroupIdorg.slf4j/groupIdartifactIdslf4j-api/artifactIdscopeprovided/scope/dependency/dependencies/project四、引入方使用4.1 添加依赖dependencygroupIdcom.example/groupIdartifactIdexample-uc-token-starter/artifactIdversion1.0.0/version/dependency4.2 配置文件app:uc:auth-center:url:https://auth.example.comclient-id:my-service-clientclient-password:secret1234.3 业务代码中使用RestControllerpublicclassOrderController{GetMapping(/api/orders)publicResultlistOrders(){// 直接通过静态方法获取当前登录用户信息IntegermemberIdUcTokenUtil.getMemberId();IntegeruserIdUcTokenUtil.getUserId();StringuserNameUcTokenUtil.getName();// 业务逻辑...returnorderService.listByMemberId(memberId);}}4.4 服务间 Token 获取后端调后端ServicepublicclassInternalApiService{ResourceprivateUcTokenUtilucTokenUtil;/** * 获取目标平台的访问Token用于跨平台调用. */publicStringgetTargetPlatformToken(StringuserId,StringplatformId){UcAccessTokenResult.UcAccessTokentokenucTokenUtil.targetAccessToken(userId,platformId);returntoken!null?token.getAccessToken():null;}/** * 刷新即将过期的Token. */publicStringrefreshToken(DefaultGenAccessTokenBodybody,StringoldToken){UcAccessTokenResult.UcAccessTokentokenucTokenUtil.refreshAccessToken(body,oldToken);returntoken!null?token.getAccessToken():null;}}4.5 自定义 Token 内容扩展模板方法ComponentpublicclassCustomGenAccessTokenBodyextendsDefaultGenAccessTokenBody{ResourceprivateUserRepositoryuserRepository;OverrideprotectedMapString,StringloadAdditional(IntegerucAccountId){// 从数据库查用户额外信息写入TokenUserEntityuseruserRepository.findByUcAccountId(ucAccountId);MapString,StringadditionalnewHashMap();additional.put(member_id,user.getMemberId().toString());additional.put(avatar_address,user.getAvatar());returnadditional;}OverrideprotectedSetStringloadUserRoles(IntegerucAccountId){returnuserRepository.findRolesByAccountId(ucAccountId);}}五、关键设计总结设计要点实现方式收益零侵入获取用户信息静态方法 SecurityContextHolder业务代码一行调用无需注入任何 Bean多场景 Token 操作targetToken/genToken/refreshToken支持跨平台跳转、后端生成、无感续期Token 内容可扩展DefaultGenAccessTokenBody 模板方法子类覆写 loadAdditional 自定义 claim配置外置Environment.getProperty不同环境不同认证中心地址兼容多种认证来源OAuth2AuthenticationDetails / HashMap 双分支既支持标准 OAuth2 请求也支持 Feign 内部传递降级容错decodedDetails 为空时通过 TokenStore 重读覆盖 Spring Security 版本差异导致的兼容问题依赖最小化核心依赖 provided scope不强制引入额外传递性依赖

相关新闻

智能体系统设计模式解析与应用实践

智能体系统设计模式解析与应用实践

1. 智能体设计模式全景概述在当今AI技术快速发展的背景下,智能体(Agent)系统已成为解决复杂问题的关键架构。不同于传统的单次模型调用,智能体系统通过自主决策、多步骤工作流管理和工具使用能力,能够处理更加开放和动态的任务场景。设计模式…

2026/7/24 2:00:03 阅读更多 →
抖音算法突变应对方案:用AI自动化实现流量翻倍的5个关键动作(2024最新版)

抖音算法突变应对方案:用AI自动化实现流量翻倍的5个关键动作(2024最新版)

更多请点击: https://intelliparadigm.com 第一章:抖音算法突变的本质洞察与AI应对范式迁移 抖音算法并非线性演进的静态规则集,而是一个由实时用户反馈、多模态内容理解、跨域行为建模与商业目标动态博弈共同驱动的闭环强化学习系统。近期…

2026/7/24 1:59:03 阅读更多 →
本地口碑好的液压多路阀生产厂家推荐

本地口碑好的液压多路阀生产厂家推荐

本地口碑好的矿山井下铲运机多路阀选型与故障解决 - 德州迈拓VG35多路阀在矿山井下作业中,铲运机的液压多路阀面临着高粉尘、潮湿等恶劣环境挑战,容易出现换向卡顿、内泄等故障。德州迈拓液压的VG35多路阀,凭借其优质的结构与工艺&#xff0c…

2026/7/24 1:59:03 阅读更多 →

最新新闻

基于YOLO与SpringBoot的智能车辆检测系统设计与优化

基于YOLO与SpringBoot的智能车辆检测系统设计与优化

1. 项目背景与核心价值在智能交通管理和自动驾驶技术快速发展的今天,车辆识别检测系统已成为城市数字化建设的基础设施。这个基于YOLO系列算法与SpringBoot框架的系统,实现了从算法选型到工程落地的完整闭环。不同于传统方案,我们采用前后端分…

2026/7/24 2:15:07 阅读更多 →
锂离子电池SOH预测:RNN、LSTM与GRU对比实践

锂离子电池SOH预测:RNN、LSTM与GRU对比实践

1. 项目背景与核心价值锂离子电池健康状态(SOH)预测是电池管理系统中的关键技术难点。作为在电动汽车、储能系统等领域广泛应用的核心部件,电池的性能衰减直接影响设备可靠性和安全性。传统基于电化学模型的预测方法存在建模复杂、适应性差等问题,而基于…

2026/7/24 2:15:07 阅读更多 →
SPI简述

SPI简述

本文章是对SPI串行外设接口的简要总结描述,希望里面的内容可以让大家对SPI有更加直观的了解,文中若存在表述不妥或错误之处,欢迎各位批评指正。。 定义 一种同步串行传输规范,也是一种单片机外设芯片串行扩展接口。 作用 主要用…

2026/7/24 2:15:07 阅读更多 →
MSPM0定时器实战:输入捕获与输出比较模式深度解析与应用

MSPM0定时器实战:输入捕获与输出比较模式深度解析与应用

1. 项目概述与核心价值在嵌入式开发,尤其是基于ARM Cortex-M0内核的MSPM0系列微控制器项目中,定时器(TIMx)模块的深度掌握是区分“能跑”和“跑得稳、跑得准”的关键分水岭。很多开发者初期可能只满足于用定时器产生一个简单的延时…

2026/7/24 2:15:07 阅读更多 →
Codex自定义代码审查规则:从基础配置到团队落地实践

Codex自定义代码审查规则:从基础配置到团队落地实践

1. 先搞清楚 Codex 自定义代码审查规则到底解决什么问题如果你在团队里负责代码质量,或者经常需要处理拉取请求(Pull Request),肯定遇到过这种情况:每次评审都要重复检查相同的编码规范、安全规则或团队约定。比如“不…

2026/7/24 2:15:07 阅读更多 →
Ship大模型评测:端点性能优化与成本降低50%的工程实践

Ship大模型评测:端点性能优化与成本降低50%的工程实践

最近在测试几个大语言模型时,我发现一个有趣的现象:当我把同样一段技术文档分别丢给不同模型处理时,有些模型虽然响应速度很快,但回答总是停留在表面;而另一些模型虽然思考深入,但等待时间长得让人失去耐心…

2026/7/24 2:14:07 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻