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

如何基于条件跳过Spring Security FilterChain,切换SSO与基础认证

解决Spring Security根据配置跳过SSO FilterChain的问题

方案一:条件化注册SSO FilterChain Bean

最直接的方式是通过配置属性控制是否创建这个高优先级的SSO FilterChain。当SSO未启用时,该Bean不会被注册,请求会自动流向优先级更低的基础认证FilterChain。

修改后的代码:

@Bean
@Order(10)
@ConditionalOnProperty(name = "sso.enabled", havingValue = "true") // 替换为你的配置属性键
protected SecurityFilterChain samlFilterChain(final HttpSecurity http) throws Exception {
    OpenSamlAuthenticationProvider authenticationProvider = new OpenSamlAuthenticationProvider();
    authenticationProvider.setResponseAuthenticationConverter(groupsConverter());
    
    http.csrf().disable()
            .authorizeHttpRequests(authorize -> authorize
                    .antMatchers("/**")
                    .permitAll()
                    .anyRequest().authenticated()
            )
            .saml2Login(saml2 -> saml2
                    .authenticationManager(new ProviderManager(authenticationProvider))
            )
            .saml2Login()
            .successHandler(successRedirectHandler())
            .failureHandler(failureRedirectHandler())
            .and()
            .saml2Logout(Customizer.withDefaults());

    return http.build();
}
  • 当配置属性sso.enabled为false时,这个@Order(10)的FilterChain不会被加载,请求会直接进入后续的基础认证FilterChain(确保基础认证FilterChain的Order值大于10,比如100)。

方案二:在当前FilterChain中直接传递请求(强制跳过)

如果无法通过条件化注册Bean,可在FilterChain中添加自定义过滤器,当SSO未启用时直接将请求传递给下一个FilterChain,不做任何拦截处理。

修改后的代码:

@Bean
@Order(10)
protected SecurityFilterChain samlFilterChain(final HttpSecurity http) throws Exception {
    if (!isSsoEnabled) {
        // 添加自定义过滤器,直接转发请求到下一个FilterChain
        http.addFilterBefore(new OncePerRequestFilter() {
            @Override
            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
                filterChain.doFilter(request, response);
            }
        }, UsernamePasswordAuthenticationFilter.class);
        // 配置所有请求直接放行,避免当前链拦截
        http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
        return http.build();
    }

    // SSO启用时的原有配置
    OpenSamlAuthenticationProvider authenticationProvider = new OpenSamlAuthenticationProvider();
    authenticationProvider.setResponseAuthenticationConverter(groupsConverter());
    
    http.csrf().disable()
            .authorizeHttpRequests(authorize -> authorize
                    .antMatchers("/**")
                    .permitAll()
                    .anyRequest().authenticated()
            )
            .saml2Login(saml2 -> saml2
                    .authenticationManager(new ProviderManager(authenticationProvider))
            )
            .saml2Login()
            .successHandler(successRedirectHandler())
            .failureHandler(failureRedirectHandler())
            .and()
            .saml2Logout(Customizer.withDefaults());

    return http.build();
}
  • 核心逻辑是通过自定义OncePerRequestFilter调用filterChain.doFilter(),实现你想要的请求传递效果;同时配置authorizeHttpRequests允许所有请求,确保当前链不会对请求做任何拦截处理。

为什么原代码的http.anonymous()无效?

http.anonymous()只是允许匿名用户访问请求,但会让当前FilterChain完成处理流程,不会将请求传递给下一个FilterChain。如果后续有基础认证的FilterChain,会因为当前链已经放行请求而无法触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 12:05:21