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

Spring Authorization Server v1.1.3中Remember Me的autoLogin未触发问题排查

问题

基于Spring Authorization Server(v1.1.3)实现多Web应用SSO功能,同时为身份提供商添加用户管理及全局管理REST接口,客户端均为Spring Cloud Gateway BFF架构的React SPA。参考官方示例项目后功能正常,但启用Remember Me时autoLogin方法始终未触发,每次都跳转到表单登录页。首次登录后remember me token已正确持久化,后续请求也携带对应cookie。

安全配置代码如下:

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
                .oidc(Customizer.withDefaults());
        http
                .exceptionHandling(exception -> exception
                        .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")))
                .cors(Customizer.withDefaults())
                .csrf(CsrfConfigurer::disable);
        return http.build();
    }

    @Bean
    @Order(2)
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http,
                                                          RememberMeServices rememberMeServices) throws Exception {
        http
                .authorizeHttpRequests(authorize -> authorize
                        .anyRequest().authenticated())
                .oauth2ResourceServer(resourceServer -> resourceServer.jwt(Customizer.withDefaults()))
                .formLogin(Customizer.withDefaults())
                .rememberMe(remember -> remember.rememberMeServices(rememberMeServices))
                .cors(Customizer.withDefaults())
                .csrf(CsrfConfigurer::disable);
        return http.build();
    }

    @Bean
    public RememberMeServices rememberMeServices(UserDetailsService userDetailsService,
                                                 PersistentTokenRepository persistentTokenRepository) {
        return new PersistentTokenBasedRememberMeServices("superSecretKey", userDetailsService, persistentTokenRepository);
    }

    ...
}

RememberMeAuthenticationFilter已存在于SecurityFilterChain中,但根据FilterOrderRegistration的设计,它位于DefaultLoginPageGeneratingFilter之后,而Spring Security官方文档指出它应该紧跟在UsernamePasswordAuthenticationFilter之后。

解决方法

问题核心是RememberMeAuthenticationFilter的顺序错误,导致在触发自动登录逻辑前,请求已被引导至登录页面。以下是两种可行的修复方案:

方案1:手动调整过滤器顺序

在defaultSecurityFilterChain中,通过addFilterAfter手动将RememberMeAuthenticationFilter放置在UsernamePasswordAuthenticationFilter之后,覆盖默认顺序:

@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http,
                                                      RememberMeServices rememberMeServices) throws Exception {
    // 获取Spring Security自动配置的UsernamePasswordAuthenticationFilter
    UsernamePasswordAuthenticationFilter usernamePasswordFilter = 
        http.getSharedObject(UsernamePasswordAuthenticationFilter.class);
    
    http
            .authorizeHttpRequests(authorize -> authorize
                    .anyRequest().authenticated())
            .oauth2ResourceServer(resourceServer -> resourceServer.jwt(Customizer.withDefaults()))
            .formLogin(Customizer.withDefaults())
            .rememberMe(remember -> remember.rememberMeServices(rememberMeServices))
            // 手动指定过滤器顺序,确保紧跟在用户名密码认证过滤器之后
            .addFilterAfter(new RememberMeAuthenticationFilter(
                http.getSharedObject(AuthenticationManager.class), 
                rememberMeServices
            ), UsernamePasswordAuthenticationFilter.class)
            .cors(Customizer.withDefaults())
            .csrf(CsrfConfigurer::disable);
    return http.build();
}

方案2:全局调整过滤器默认顺序

通过自定义FilterOrderRegistration Bean,修改Spring Security的默认过滤器顺序规则,确保RememberMeAuthenticationFilter始终在UsernamePasswordAuthenticationFilter之后执行:

@Configuration
public class FilterOrderConfig {
    @Bean
    public FilterOrderRegistration filterOrderRegistration() {
        FilterOrderRegistration registration = new FilterOrderRegistration();
        // 将RememberMe过滤器的顺序设置为用户名密码过滤器顺序+1
        registration.put(RememberMeAuthenticationFilter.class, 
            FilterOrderRegistration.getOrder(UsernamePasswordAuthenticationFilter.class) + 1);
        return registration;
    }
}

额外验证项

  • 确认PersistentTokenRepository的实现(如JDBC/JPA)配置正确,token能正常写入和读取数据库。
  • 生产环境中替换硬编码的superSecretKey为安全的随机密钥,可通过配置文件注入。
  • 检查请求中的remember me cookie名称是否与PersistentTokenBasedRememberMeServices默认的remember-me一致,若自定义名称需在rememberMeServices中显式设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 06:05:02