Spring Security JWT访问端点返回403 Forbidden问题排查
Spring Boot + Security + JWT 403 Forbidden 问题排查与解决
一、核心排查方向
- 过滤器执行顺序错误:JwtAuthenticationFilter 必须放在
UsernamePasswordAuthenticationFilter之前,否则权限校验会在JWT认证信息填充前触发 - 权限配置优先级冲突:Security规则匹配是从上到下、匹配即停止,如果匿名放行规则写在全局认证规则之后,会被覆盖失效
- JWT解析后未注入Security上下文:解析token成功后,必须将认证对象存入
SecurityContextHolder,否则Security无法识别已认证用户 - CORS配置缺失:跨域场景下,OPTIONS预检请求被拦截会导致实际请求返回403
- 路径匹配错误:确认
/register是否属于/api/v1/auth/**范围,或是否有其他自定义拦截器拦截了请求
二、针对你场景的具体检查步骤
1. 验证过滤器顺序
检查Security配置中过滤器添加方式是否正确:
// 正确写法:将JwtAuthenticationFilter放在UsernamePasswordAuthenticationFilter之前 http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
若使用addFilterAfter,会导致权限校验先执行,此时Security上下文无JWT认证信息,直接返回403
2. 检查权限规则顺序
确保匿名放行规则在全局认证规则之前:
http.authorizeHttpRequests(auth -> auth // 先放行匿名路径 .requestMatchers("/api/v1/auth/**").permitAll() // 再设置其他路径需认证 .anyRequest().authenticated() );
顺序颠倒的话,anyRequest().authenticated()会先匹配所有请求,导致匿名放行规则失效
3. 检查JwtAuthenticationFilter核心逻辑
确认解析token后正确注入Security上下文:
// 在doFilterInternal方法中 Authentication authentication = jwtTokenProvider.getAuthentication(token); // 必须将认证对象存入上下文,否则Security无法识别 SecurityContextHolder.getContext().setAuthentication(authentication); // 继续执行后续过滤器链 filterChain.doFilter(request, response);
缺少上下文注入步骤的话,Security会判定请求未认证,返回403
4. 补充CORS配置(跨域场景)
如果是前端跨域请求,需在Security中配置CORS:
http.cors(cors -> cors.configurationSource(corsConfigurationSource())); // 自定义CORS配置源 private CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Collections.singletonList("*")); // 生产环境替换为具体域名 config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; }
OPTIONS预检请求被拦截会导致实际请求因跨域限制返回403
5. 分析DEBUG日志关键点
重点查看日志中以下内容:
- 过滤器执行顺序:确认JwtAuthenticationFilter是否在权限校验过滤器前执行
- SecurityContext状态:请求处理过程中是否存在有效的Authentication对象
- 请求匹配结果:确认
/api/v1/auth/**是否被正确匹配到permitAll规则
三、常见错误示例及修复
错误示例1:过滤器顺序错误
// 错误:将JWT过滤器放在了认证过滤器之后 http.addFilterAfter(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
修复:改为addFilterBefore
错误示例2:权限规则顺序错误
http.authorizeHttpRequests(auth -> auth .anyRequest().authenticated() .requestMatchers("/api/v1/auth/**").permitAll() // 此规则永远不会被匹配 );
修复:调换规则顺序,先写匿名放行规则
错误示例3:未注入Security上下文
// 仅解析token但未存入上下文 Authentication authentication = jwtTokenProvider.getAuthentication(token); // 缺少SecurityContextHolder.getContext().setAuthentication(authentication); filterChain.doFilter(request, response);
修复:添加上下文注入代码
内容的提问来源于stack exchange,提问作者Nectar
相关产品推荐
相关产品推荐

