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

Spring Security SAML2登录成功后如何仅执行一次过滤器/处理器?

解决方案:SAML2登录成功后仅执行一次自定义Cookie设置

针对你的需求,有两种可靠的实现方式,都能确保仅在SAML2登录成功时触发一次Cookie设置逻辑:

方案一:使用认证成功事件监听器

Spring Security会在认证成功时发布AuthenticationSuccessEvent事件,我们可以监听这个事件,并判断是否为SAML2认证,再执行Cookie设置逻辑:

1. 实现事件监听器

@Component
public class Saml2LoginSuccessListener implements ApplicationListener<AuthenticationSuccessEvent> {

    @Override
    public void onApplicationEvent(AuthenticationSuccessEvent event) {
        Authentication authentication = event.getAuthentication();
        // 仅处理SAML2认证成功的情况
        if (authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal) {
            // 获取当前请求响应
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            if (response != null) {
                // 自定义Cookie逻辑
                Cookie customCookie = new Cookie("custom-token", "your-generated-token");
                customCookie.setPath("/");
                // 按需配置Cookie属性:HttpOnly、Secure等
                customCookie.setHttpOnly(true);
                customCookie.setSecure(true);
                response.addCookie(customCookie);
            }
        }
    }
}

说明

  • 该监听器仅在认证成功时触发一次,不会在后续请求中重复执行
  • 通过Saml2AuthenticatedPrincipal判断是否为SAML2登录,避免处理其他认证方式的成功事件
  • Spring Web环境默认支持通过RequestContextHolder获取当前请求上下文

方案二:自定义SAML2登录成功处理器

直接配置Spring Security的SAML2登录专属成功处理器,这是更精准的方式,仅针对SAML2登录流程:

1. 自定义登录成功处理器

@Component
public class CustomSaml2AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        // 仅处理SAML2认证
        if (authentication.getPrincipal() instanceof Saml2AuthenticatedPrincipal) {
            // 设置自定义Cookie
            Cookie customCookie = new Cookie("custom-token", "your-generated-token");
            customCookie.setPath("/");
            customCookie.setHttpOnly(true);
            customCookie.setSecure(true);
            response.addCookie(customCookie);
        }
        // 调用父类方法,保留默认跳转逻辑(比如跳转到登录前的受保护页面)
        super.onAuthenticationSuccess(request, response, authentication);
    }
}

2. 在Security配置中绑定处理器

修改你的SAMLConfiguration配置类,将自定义处理器配置到saml2Login流程中:

@Configuration
public class SAMLConfiguration {

    @Autowired
    private CustomSaml2AuthenticationSuccessHandler saml2SuccessHandler;

    @Bean
    SecurityFilterChain configure(HttpSecurity http) throws Exception {
        OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider();

        Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationRepository, new OpenSamlMetadataResolver());
        http.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);

        http.authorizeHttpRequests(requests -> requests
                .requestMatchers("/saml2/service-provider-metadata/**")
                .permitAll()
        ).saml2Login(saml2 -> saml2
                .authenticationManager(new ProviderManager(authenticationProvider))
                .relyingPartyRegistrationRepository(relyingPartyRegistrationRepository)
                // 绑定自定义成功处理器
                .successHandler(saml2SuccessHandler)
        ).saml2Logout(withDefaults());
    }
}

说明

  • 该处理器是SAML2登录流程的专属回调,只会在SAML2登录成功时执行一次
  • 继承SavedRequestAwareAuthenticationSuccessHandler可以保留默认的跳转逻辑,若不需要可直接实现AuthenticationSuccessHandler接口

为什么之前的方案失效?

  • SetToken过滤器:你将它添加到了全局过滤器链中,所有请求都会经过该过滤器,无法实现仅登录时执行的逻辑
  • SessionAuthenticationStrategy:当设置SessionCreationPolicy.STATELESS时,Spring Security不会创建会话,每次请求都会重新触发认证逻辑;即使是有状态会话,该策略也会在会话重新认证时触发,不符合仅执行一次的需求

内容的提问来源于stack exchange,提问作者Sumeet Kumar Yadav

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 22:38:24