Spring Security自定义认证实现调用API出现403错误求助
自定义Spring Security认证后403问题排查
1. 验证过滤器执行状态
- 在
SessionTokenFilter的doFilterInternal方法中添加日志,确认请求进入时过滤器是否被触发。如果没有日志输出,检查SecurityConfiguration中是否正确通过addFilterBefore/addFilterAfter将过滤器加入链中,且位置合理(建议放在UsernamePasswordAuthenticationFilter之前)。 - 核对请求头字段名是否与前端一致,比如你用的是
X-Session-Token还是Authorization,确保request.getHeader()的参数拼写无误。
2. 检查自定义Authentication对象
- 确认自定义Authentication类正确实现
Authentication接口:getAuthorities()方法必须返回非空集合(哪怕是new ArrayList<>()),Spring Security会认为空权限集合无访问资格,直接返回403。- 已认证状态的对象需将
authenticated属性设为true,可以通过构造方法或setAuthenticated(true)设置(注意:自定义对象若直接调用setAuthenticated,需重写该方法避免抛出异常)。
3. 确认AuthenticationProvider配置与逻辑
- 确保
SessionAuthenticationProvider被Spring容器管理(添加@Component注解,或在SecurityConfiguration中手动注册到AuthenticationManagerBuilder):@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(sessionAuthenticationProvider); } - 检查
supports(Class<?> authentication)方法:必须返回true来匹配你的自定义Authentication类型,比如:
若返回@Override public boolean supports(Class<?> authentication) { return SessionTokenAuthentication.class.isAssignableFrom(authentication); }false,Provider会拒绝处理该认证对象,导致认证失败。 - 验证
authenticate方法的返回值:token校验通过后,必须构建包含有效权限的已认证对象,示例:UserDetails userDetails = userDetailsService.loadUserByToken(token); return new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities() // 此处权限集合不可为空 );
4. 核对SecurityConfiguration权限规则
- 确认端点权限配置正确:如果需要认证后访问,需配置
.anyRequest().authenticated();若部分端点允许匿名,需明确.antMatchers("/public/**").permitAll()。 - 前后端分离场景下,务必禁用CSRF,否则POST/PUT等请求会被拦截:
http.csrf(csrf -> csrf.disable()); - 检查过滤器顺序是否正确,比如:
http.addFilterBefore(sessionTokenFilter, UsernamePasswordAuthenticationFilter.class);
5. 利用Spring Security日志定位问题
从跟踪日志中重点排查以下节点:
- 是否有
SessionTokenFilter的执行日志?无日志则说明过滤器未加入链中。 SessionAuthenticationProvider的authenticate方法是否被调用?未调用则检查supports方法逻辑。- 认证成功后,
SecurityContextHolder中是否存在已认证的Authentication对象?若不存在,说明认证结果未被正确存入上下文。 - 查找
AccessDeniedException的堆栈信息,明确是权限不足还是认证未通过导致的403。
6. 常见避坑点
- 不要让
getAuthorities()返回null,即使是无权限的用户,也返回空集合而非null。 - 无状态认证场景下,确保
SecurityContextHolder的线程绑定策略正确(默认MODE_THREADLOCAL即可),避免请求线程间上下文丢失。 - 若存在CORS过滤器,需确保其在Spring Security过滤器之前执行,避免请求头被过滤导致token无法获取。
内容的提问来源于stack exchange,提问作者Harsh Kanakhara
相关产品推荐
相关产品推荐

