新闻详情

新闻详情

首页 / 资讯中心 / 详情

Spring Security 与 OAuth2 的关系:从过滤器链到 Token 校验的配置骨架

发布时间:2026/9/28 18:10:58来源:尧图网络
Spring Security 与 OAuth2 的关系:从过滤器链到 Token 校验的配置骨架
1. 从一次 401 说起过滤器链到底卡在哪很多 Java 后端同学第一次把 Spring Security 和 OAuth2 拼在一起时都会遇到一个很迷惑的现象明明请求头里带了Authorization: Bearer xxx接口却还是返回 401日志里也看不出所以然。这个问题的根源往往不是 Token 本身有问题而是没搞清楚 Spring Security 的过滤器链和 OAuth2 资源服务器到底谁先谁后、谁负责什么。简单说Spring Security 是一套「认证 授权」的框架核心是一组按顺序执行的过滤器链FilterChain。它管的是「你是谁、你能干什么」。而 OAuth2 是一套授权协议它定义了怎么拿 Token、怎么用 Token 访问资源。在 Spring 生态里OAuth2 资源服务器的能力是「挂」在 Spring Security 过滤器链上的一个环节它负责从请求头里解析 Bearer Token然后交给 Spring Security 的上下文去判断权限。所以两者的关系可以这样理解Spring Security 是骨架和调度中心OAuth2 是其中一种具体的认证方式。你配置的SecurityFilterChain决定了哪些请求需要认证、用哪种方式认证而 OAuth2 资源服务器配置决定了 Token 怎么校验、校验通过后用户身份和权限怎么放进SecurityContext。这篇文章面向正在做 Spring Boot 后端、需要把 OAuth2 资源服务器接进 Spring Security 的开发者。我会给出一套可以直接复制的SecurityConfig和application.yml骨架然后用 curl 验证 Token 校验是否真的生效最后把常见的坑列出来。适合谁已经知道 JWT 大概长什么样、但被过滤器链顺序和配置类搞晕的人。2. 前置准备依赖、密钥与 TaoToken 接入信息在写配置之前先把依赖和基础信息准备好。这里我用 Spring Boot 3.x Spring Security 6.x 的组合OAuth2 资源服务器用spring-boot-starter-oauth2-resource-server这是目前官方推荐的方式不再依赖老的spring-security-oauth2那一套。dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-oauth2-resource-server/artifactId /dependency如果你手上还没有可用的 Token 签发环境或者想先拿一个标准格式的 JWT 来验证资源服务器的校验逻辑可以用 TaoToken 的模型对话或 API Keys 页面生成一个测试用的 Key再配合它的接入文档确认请求头格式。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。注意 API 地址不带 UTM 参数直接用它做 base url 即可。资源服务器校验 Token 有两种主流方式一种是 JWT 本地校验用公钥验签不查授权中心另一种是 opaque token 远程校验把 Token 转发给授权中心 introspect 接口。本地校验性能好、无网络依赖适合大多数场景。下面我以 JWT 本地校验为主线因为它最能体现「过滤器链 OAuth2」的衔接点。你需要准备一个 JWK Set URI也就是授权中心暴露公钥的地址形如https://your-auth-server/oauth2/jwks。如果你用的是 TaoToken 这类服务可以在接入文档里找到对应的 JWKS 地址。拿到之后填进application.yml。3. 可复制配置SecurityFilterChain 与 application.yml 骨架先看application.yml这里定义了资源服务器的 issuer 和 jwk-set-uriSpring Security 会自动拉取公钥并缓存。spring: security: oauth2: resourceserver: jwt: issuer-uri: https://your-auth-server jwk-set-uri: https://your-auth-server/oauth2/jwks server: port: 8080注意issuer-uri和jwk-set-uri二选一即可如果两个都写Spring 会优先用jwk-set-uri。issuer-uri的好处是它会自动校验 Token 里的iss字段安全性更高。接下来是核心的SecurityConfig。这里我用 Spring Security 6 的 Lambda DSL 写法SecurityFilterChainBean 取代了老的WebSecurityConfigurerAdapter。import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(csrf - csrf.disable()) .sessionManagement(session - session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth - auth .requestMatchers(/public/**).permitAll() .requestMatchers(/user/**).hasAuthority(SCOPE_user) .requestMatchers(/admin/**).hasAuthority(SCOPE_admin) .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 - oauth2 .jwt(jwt - jwt .jwtAuthenticationConverter(jwtAuthenticationConverter()) ) ); return http.build(); } private org.springframework.core.convert.converter.Converter org.springframework.security.oauth2.jwt.Jwt, org.springframework.security.authentication.AbstractAuthenticationToken jwtAuthenticationConverter() { org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter converter new org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter(); org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter authoritiesConverter new org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter(); authoritiesConverter.setAuthorityPrefix(SCOPE_); authoritiesConverter.setAuthoritiesClaimName(scope); converter.setJwtGrantedAuthoritiesConverter(authoritiesConverter); return converter; } }这段配置里最关键的是.oauth2ResourceServer(oauth2 - oauth2.jwt(...))。它做的事情是在 Spring Security 过滤器链中插入BearerTokenAuthenticationFilter这个过滤器会从Authorization头里取出 Bearer Token然后交给JwtAuthenticationProvider去验签、解析 claims最后把结果放进SecurityContext。后面的authorizeHttpRequests规则才有东西可判断。jwtAuthenticationConverter的作用是把 JWT 里的scope字段映射成 Spring Security 的权限。默认情况下JwtGrantedAuthoritiesConverter会把 scope 值加上SCOPE_前缀所以配置里写hasAuthority(SCOPE_user)才能匹配上。如果你 Token 里的权限字段叫authorities或roles改setAuthoritiesClaimName即可。4. 验证请求用 curl 确认 Token 校验真的生效配置写完启动应用。接下来用 curl 做三组验证分别对应「无 Token」「有 Token 但权限不够」「有 Token 且权限正确」。第一组不带 Token 访问受保护接口curl -i http://localhost:8080/user/profile预期返回401 Unauthorized响应头里会有WWW-Authenticate: Bearer。这说明BearerTokenAuthenticationFilter没找到 Token直接判定未认证。第二组带一个格式正确但 scope 不含user的 Tokencurl -i -H Authorization: Bearer your-token http://localhost:8080/user/profile预期返回403 Forbidden。注意这里和 401 的区别401 是「你没认证」403 是「你认证了但没权限」。如果这里返回 401说明 Token 验签失败检查jwk-set-uri是否可达、Token 是否过期。第三组带一个 scope 包含user的 Tokencurl -i -H Authorization: Bearer your-token http://localhost:8080/user/profile预期返回200 OK和业务数据。到这一步说明过滤器链、OAuth2 资源服务器、权限映射三者已经串通了。如果你想更直观地看 Token 解析结果可以在 Controller 里注入Jwt对象import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; RestController public class ProfileController { GetMapping(/user/profile) public String profile(AuthenticationPrincipal Jwt jwt) { return subject jwt.getSubject() , scope jwt.getClaimAsString(scope); } }访问成功后返回的字符串里能看到sub和scope这就证明 Token 里的信息确实被解析并传到了业务层。5. 本篇常见错排查401、403 与过滤器顺序第一个高频错误配置了oauth2ResourceServer但依然返回 401且日志里没有验签失败信息。这通常是jwk-set-uri写错或网络不通Spring 拉不到公钥验签直接失败。排查方法是在启动日志里搜jwk看有没有Fetching JWK Set相关记录。如果用的是 TaoToken 的接入文档里的 JWKS 地址确认路径没有多余斜杠。第二个错误hasAuthority(user)匹配不上。原因是默认权限前缀是SCOPE_你写user自然匹配不到SCOPE_user。要么改配置里的setAuthorityPrefix()要么在规则里写全SCOPE_user。我建议保留前缀因为这样能区分 OAuth2 的 scope 和其他来源的权限。第三个错误自定义了一个Filter想手动解析 Token结果和BearerTokenAuthenticationFilter冲突。记住一旦启用oauth2ResourceServerToken 解析这件事就交给它了你的自定义过滤器应该放在它之后从SecurityContext里拿已经解析好的Authentication而不是重新解析一遍请求头。第四个错误SessionCreationPolicy.STATELESS没配导致 Spring Security 尝试创建 Session在分布式环境下出现状态不一致。资源服务器必须是无状态的这一行不能省。第五个错误issuer-uri配了但 Token 里的iss对不上返回 401。这种情况日志里会有Jwt issuer validation failed。检查授权中心实际签发的iss值和配置里的是否完全一致包括末尾斜杠。6. 把 Token 校验接进你的编码链路到这里Spring Security 和 OAuth2 的衔接点应该清楚了SecurityFilterChain负责定义规则和顺序oauth2ResourceServer负责插入 Token 解析过滤器JwtAuthenticationConverter负责把 claims 翻译成权限。三者缺一不可。如果你接下来要在本地长期跑这套资源服务器或者用它对接多个下游服务做联调建议把 Token 的获取和刷新也纳入日常流程。TaoToken 的 Coding Plan 适合这种需要反复验证 Token 校验、又不想每次手动换 Key 的场景入口在 https://taotoken.net/api 对应的控制台里可以找到。需要生成新的测试 Key 时直接去 API Keys 页面操作接入文档里有完整的请求头示例。最后留一个实用技巧在application.yml里把logging.level.org.springframework.securityDEBUG打开启动后你会看到过滤器链的完整顺序以及每个请求经过了哪些过滤器。这比任何文档都直观排障时先看这行日志能省掉大半猜测时间。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

GD32H759+RT-Thread驱动ST7789:SPI+DMA刷屏实战与避坑指南 2026/9/28 19:48:22

GD32H759+RT-Thread驱动ST7789:SPI+DMA刷屏实战与避坑指南

1. 从点灯到刷屏:为什么SPI是工控HMI绕不开的一道坎做GD32H759加RT-Thread这套组合的工控项目,走到第6篇,基本都会碰到同一个需求:把采集到的数据、设备状态、报警信息实时显示到一块彩屏上。这时候SPI就绕不开了。我接触过的工控…

阅读更多 →
trae使用经验阶段性总结1:用TaoToken统一Key跑通arcpy与Python脚本 2026/9/28 19:48:22

trae使用经验阶段性总结1:用TaoToken统一Key跑通arcpy与Python脚本

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
电控简历没回音?10个开源项目帮你补齐工程经历,秋招突围 2026/9/28 19:48:22

电控简历没回音?10个开源项目帮你补齐工程经历,秋招突围

秋招的群里天天有人问"投了电控方向几十份简历,怎么一点回音都没有",说实话,这个问题我在带项目的时候见得太多了。学历漂亮、绩点不错,可简历往技术岗那一栏看,除了课程设计和课设实验之外,几乎…

阅读更多 →
AI编码代理上下文工程:ChatMemory滑动窗口与Context-mode MCP 2026/9/28 19:48:22

AI编码代理上下文工程:ChatMemory滑动窗口与Context-mode MCP

1. AI编码代理的上下文困境:为什么"记不住"和"记太多"会同时出现做AI编码代理的人,无论是重度用户还是自己写Agent框架的开发者,迟早都会撞上同一堵墙:上下文管理。我最早接触Claude Code这类工具的时候&…

阅读更多 →
DevEco Code 写鸿蒙 ArkTS 确实快,但我把默认引擎换成 Cursor 后补上了 TaoToken 配置 2026/9/28 19:48:22

DevEco Code 写鸿蒙 ArkTS 确实快,但我把默认引擎换成 Cursor 后补上了 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
【OpenAI】Google开源神器Computer Use Preview全攻略:用AI自然语言轻松实现浏览器自动化任务获取OpenAI API KEY的两种方式,开发者必看全方面教程! 2026/9/28 19:48:09

【OpenAI】Google开源神器Computer Use Preview全攻略:用AI自然语言轻松实现浏览器自动化任务获取OpenAI API KEY的两种方式,开发者必看全方面教程!

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉