You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security 6自定义AuthenticationFilter无法跳转OAuth2重定向页问题

问题:自定义登录过滤器后,OIDC授权服务器认证成功无法跳转到重定向页面

问题背景

为获取登录表单的额外自定义字段,在Spring Security 6中自定义了继承UsernamePasswordAuthenticationFilter的CustomAuthenticationFilter,以及继承UsernamePasswordAuthenticationToken的CustomAuthenticationToken。认证逻辑正常(AuthenticationProvider的authenticate方法能返回已认证的Authentication对象),但认证后停留在登录页,不会跳转到OAuth2客户端的重定向页面;不使用自定义过滤器时功能完全正常。

配置代码

安全配置类

@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class AuthenticationSecurityConfig extends AbstractHttpConfigurer<AuthenticationSecurityConfig, HttpSecurity> {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
        http.addFilterBefore(authenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        
        http.authorizeHttpRequests()
                .requestMatchers("/css/**", "/login")
                .permitAll()
                .requestMatchers("/resources/**")
                .permitAll()
                .and()
                .formLogin(form -> form
                        .loginPage("/login")
                        .permitAll()
                )
                .logout()
                .logoutUrl("/logout")
                .and()
                .authorizeHttpRequests(
                        auth -> auth.anyRequest().authenticated()
                )
                .apply(securityConfig());
        return http.build();

    }

}

项目依赖配置(build.gradle)

plugins {
    id "org.springframework.boot" version "3.0.0-RC2"
    id "io.spring.dependency-management" version "1.0.11.RELEASE"
    id "java"
}
implementation "org.springframework.security:spring-security-oauth2-authorization-server:1.0.0"

关键日志信息

.HttpSessionRequestCache : Saved request http://192.168.0.107:9000/oauth2/authorize?client_id=messaging-client&redirect_uri=http%3A%2F%2F192.168.0.107%3A8080%2Fauth%2Fsigninwin%2Fmain&response_type=code&scope=openid%20profile%20message.read&state=802af0dcd82a483eb726c1dffff0867d&code_challenge=t_tfBjZPRd228uEZuQJ56clfXokGYqiwkudQqKhWQqo&code_challenge_method=S256&prompt=login&response_mode=query&continue&continue to session
2022-11-30T19:48:05.063+08:00 DEBUG 63801 --- [nio-9000-exec-5] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://192.168.0.107:9000/login
2022-11-30T19:48:05.078+08:00 DEBUG 63801 --- [nio-9000-exec-6] o.s.security.web.FilterChainProxy : Securing GET /login
2022-11-30T19:48:05.078+08:00 DEBUG 63801 --- [nio-9000-exec-6] o.s.security.web.FilterChainProxy : Secured GET /login
2022-11-30T19:48:05.084+08:00 DEBUG 63801 --- [nio-9000-exec-6] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext

解决方案

问题根源是自定义过滤器未正确处理请求缓存(RequestCache)和认证成功后的重定向逻辑,同时过滤器添加方式引发流程冲突,修复步骤如下:

1. 完善自定义过滤器的认证成功逻辑

在CustomAuthenticationFilter中注入RequestCache,实现认证成功后跳转至缓存的授权请求地址:

public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private final RequestCache requestCache = new HttpSessionRequestCache();

    public CustomAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
        // 匹配formLogin配置的登录请求路径
        setFilterProcessesUrl("/login");
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        // 获取之前缓存的授权请求
        SavedRequest savedRequest = this.requestCache.getRequest(request, response);
        if (savedRequest != null) {
            // 移除缓存请求,避免重复跳转
            this.requestCache.removeRequest(request, response);
            // 跳转到原始授权地址
            getRedirectStrategy().sendRedirect(request, response, savedRequest.getRedirectUrl());
        } else {
            // 无缓存请求时执行默认逻辑
            super.successfulAuthentication(request, response, chain, authResult);
        }
    }
}

2. 替换默认过滤器而非添加前置过滤器

原配置中addFilterBefore会导致同时存在两个登录过滤器,引发流程冲突,修改配置类的configure方法:

@Override
public void configure(HttpSecurity http) throws Exception {
    AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
    // 替换默认的UsernamePasswordAuthenticationFilter
    http.replaceFilter(new CustomAuthenticationFilter(authenticationManager));
}

核心原因

默认的UsernamePasswordAuthenticationFilter会自动处理Spring Security的RequestCache:当用户访问受保护的/oauth2/authorize端点时,请求会被缓存,认证成功后自动跳转至缓存地址。自定义过滤器缺失该逻辑会导致停留在登录页;同时添加前置过滤器会让默认过滤器依然存在,干扰认证流程。


内容的提问来源于stack exchange,提问作者stephen yup

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 09:35:24