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

时间:2016-09-15 14:27:45

标签: java spring-mvc spring-security saml-2.0 spring-saml

我遇到与Spring Saml2相关的Spring Security配置问题,即使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();

我怀疑这是我之后有一个null身份验证的原因。

以下是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);

...
    }

这是网络初始化者:

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);
    }

}

P.S。额外信息:我主要在github上引用了以下存储库中的代码:https://github.com/vdenotaris/spring-boot-security-saml-sample/tree/master/src/main/java/com/vdenotaris/spring/boot/security/saml/web但我没有使用Spring启动。

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

1 个答案:

答案 0 :(得分:2)

我找到了答案。初始化上下文时,过滤器未正确注册,因此上述的行为很简单。

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

public class SecurityInitialiser extends SecurityWebApplicationInitializer(){}

并从onStartup类中删除WebInitialiser方法。

这在Spring启动时起作用的原因是因为过滤器会被自动扫描和注册。