自定义Spring Security AuthenticationProvider未被调用且跳转错误页排查
问题根因
从你提供的DEBUG日志可以明确判断问题核心:你仅配置了「除/hello/**外所有请求需要认证」的权限规则,但未配置任何认证入口/认证过滤器,请求携带匿名身份访问受保护路径时,Spring Security直接触发Http403ForbiddenEntryPoint拒绝访问,全程不会触发你自定义的ELPAuthenticationProvider逻辑。
排查解决步骤
- 测试自定义AuthenticationProvider有效性
你可以先在HttpSecurity配置中添加表单登录配置,验证自定义Provider是否能正常被调用:
@Override protected void configure(HttpSecurity http) throws Exception { elpLogger.debug("****************Configuring HttpSecurity"); http.authorizeRequests().antMatchers("/hello/**").permitAll(); http.authorizeRequests().anyRequest().authenticated(); // 新增表单登录配置 http.formLogin(); }
添加后访问受保护路径会自动跳转Spring Security默认登录页,输入任意账号密码即可登录,此时可观察到authenticate方法的debug日志输出,证明你的自定义Provider本身注册是正常的。
- 适配第三方授权对接场景
你要对接第三方应用完成用户授权,属于预认证场景,需要添加自定义认证过滤器,从请求中获取第三方授权凭证(比如请求头Token、Cookie等),封装为Authentication对象后交给认证管理器处理:
- 编写自定义认证过滤器:
public class ThirdPartyAuthFilter extends OncePerRequestFilter { private AuthenticationManager authenticationManager; public ThirdPartyAuthFilter(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 示例:从请求头获取第三方授权凭证 String thirdPartyToken = request.getHeader("X-Auth-Token"); if (thirdPartyToken != null) { // 封装为认证请求对象,传给自定义Provider处理 Authentication authRequest = new UsernamePasswordAuthenticationToken(thirdPartyToken, null); Authentication authResult = authenticationManager.authenticate(authRequest); // 认证成功后存入安全上下文 SecurityContextHolder.getContext().setAuthentication(authResult); } filterChain.doFilter(request, response); } }
- 将过滤器添加到Spring Security过滤器链中:
@Override protected void configure(HttpSecurity http) throws Exception { elpLogger.debug("****************Configuring HttpSecurity"); // 添加自定义过滤器,位置在用户名密码认证过滤器之前 http.addFilterBefore(new ThirdPartyAuthFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class); http.authorizeRequests().antMatchers("/hello/**").permitAll(); http.authorizeRequests().anyRequest().authenticated(); // 可选配置:如果是接口服务不需要页面跳转,自定义未授权/权限不足的响应格式 http.exceptionHandling() .authenticationEntryPoint((req, resp, e) -> { resp.setStatus(401); resp.setContentType("application/json;charset=utf-8"); resp.getWriter().write("{\"code\":401,\"message\":\"未授权,请先登录\"}"); }) .accessDeniedHandler((req, resp, e) -> { resp.setStatus(403); resp.setContentType("application/json;charset=utf-8"); resp.getWriter().write("{\"code\":403,\"message\":\"权限不足\"}"); }); // 对接API场景通常不需要csrf防护,可关闭 http.csrf().disable(); }
- 后续优化点
你当前的ELPAuthenticationProvider实现直接返回固定的认证成功对象,上线前需要补充实际校验逻辑:调用第三方授权接口验证凭证有效性、获取对应账号的权限列表等。
如果仍有问题,可将org.springframework.security的日志级别调整为TRACE,查看完整过滤器链的执行流程,确认自定义过滤器是否被正常加载。
内容的提问来源于stack exchange,提问作者mmaceachran
相关产品推荐
相关产品推荐

