Spring Saml FilterChainProxy 清除上下文 - 空身份验证

Posted

技术标签:

【中文标题】Spring Saml FilterChainProxy 清除上下文 - 空身份验证【英文标题】:Spring Saml FilterChainProxy clearing context - null Authentication 【发布时间】:2017-01-23 15:10:17 【问题描述】:

我遇到了与 Spring Saml2 相关的 Spring Security 配置问题,这导致 Authentication 始终为 null,即使 IDP 响应成功也是如此。

我将spring-security-saml2-core1.0.2.RELEASEspring 4.3.0.RELEASEspring-security 4.1.0.RELEASE 结合使用。

我有一个简单的 SP,它通过 SSOCircle 通过 SSO 进行身份验证。身份验证工作和调试我可以看到SAMLAuthenticationProvider 返回一个经过身份验证的用户,该用户具有我期望的授予权限。到目前为止一切顺利。

虽然身份验证完成后,我进入了org.springframework.security.web.FilterChainProxy:180 调用以下行

SecurityContextHolder.clearContext();

我怀疑这是我之后获得空身份验证的原因。

以下是 Spring Security 配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

...

@Bean
    public SAMLAuthenticationProvider samlAuthenticationProvider() 
        SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider();
        samlAuthenticationProvider.setUserDetails(samlUserMappingService);
        samlAuthenticationProvider.setForcePrincipalAsString(false);
        return samlAuthenticationProvider;
    

 @Bean
    public FilterChainProxy samlFilter() throws Exception 
        List<SecurityFilterChain> chains = new ArrayList<SecurityFilterChain>();

        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/login/**"), samlEntryPoint()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/logout/**"), samlLogoutFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/metadata/**"),
                metadataDisplayFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSO/**"),
                samlWebSSOProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSOHoK/**"),
                samlWebSSOHoKProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SingleLogout/**"),
                samlLogoutProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/discovery/**"), samlIDPDiscovery()));
        return new FilterChainProxy(chains);
    



@Override
protected void configure(HttpSecurity http) throws Exception 
    http.httpBasic().authenticationEntryPoint(samlEntryPoint());
    http.csrf().disable();
    //http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
    http.addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
    http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/error").permitAll().antMatchers("/saml/**")
            .permitAll().anyRequest().authenticated();
    http.logout().logoutSuccessUrl("/");



@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.authenticationProvider(samlAuthenticationProvider()).eraseCredentials(false);

...
    

这里是 Web 初始化程序:

public class WebInitialiser extends AbstractAnnotationConfigDispatcherServletInitializer 

    @Override
    protected Class<?>[] getServletConfigClasses() 
        return new Class[] ;
    

    @Override
    protected String[] getServletMappings() 
        return new String[]  "/" ;
    

    @Override
    protected Class<?>[] getRootConfigClasses() 
        return new Class[]  WebMvcConfig.class;
    

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException 
        servletContext.addFilter("samlFilter", new DelegatingFilterProxy("samlFilter"))
                .addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");

        super.onStartup(servletContext);
    


附:更多信息:我主要参考了 github 上以下存储库中的代码:https://github.com/vdenotaris/spring-boot-security-saml-sample/tree/master/src/main/java/com/vdenotaris/spring/boot/security/saml/web 但我没有使用 Spring boot。

应用部署在apache-tomcat-8.0.30上,我也试过apache-tomcat-7.0.37。

【问题讨论】:

【参考方案1】:

我找到了答案。初始化上下文时,过滤器没有正确注册,所以上面描述的奇怪行为。

解决方案是创建一个类,如下所示

public class SecurityInitialiser extends SecurityWebApplicationInitializer()

并从WebInitialiser 类中删除onStartup 方法。

这在 Spring boot 中起作用的原因是过滤器被自动扫描和注册。

【讨论】:

以上是关于Spring Saml FilterChainProxy 清除上下文 - 空身份验证的主要内容,如果未能解决你的问题,请参考以下文章

是否有用于将 SAML 与 Spring Boot 应用程序集成的 Spring Boot SAML 客户端?

ADFS 拒绝 spring-saml 元数据

Spring Boot 在本地环境中禁用 SAML 安全性

Spring SAML 扩展和 Spring Security 5

Spring-SAML 的 SSL 配置问题

Spring SAML - 用户从应用程序注销时是不是必须调用 SAML 本地注销?