本文介绍了Spring Saml FilterChainProxy 清除上下文 - null 身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a problem with Spring Security configuration relevant to Spring Saml2, which causes the Authentication to be always null even when the IDP responds successfully.

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

I am using the spring-security-saml2-core library 1.0.2.RELEASE in conjunction with spring 4.3.0.RELEASE and spring-security 4.1.0.RELEASE.

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

I have a simple SP which authenticates through SSO via SSOCircle. The authentication works and debugging I can see the SAMLAuthenticationProvider returning an authenticated User with the granted authorities I expected. So far so good.

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

Although when the authentication completes I stepped into a org.springframework.security.web.FilterChainProxy:180 calling the following line

SecurityContextHolder.clearContext();

我怀疑这是我之后进行空身份验证的原因.

which I suspect it is the reason I have a null Authentication afterwards.

以下是 Spring Security 配置:

Following is the Spring Security configuration:

@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 初始化程序:

And here is the Web initialiser:

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.

P.S. for extra info: I have mainly referred to the code from the following repository on github: https://github.com/vdenotaris/spring-boot-security-saml-sample/tree/master/src/main/java/com/vdenotaris/spring/boot/security/saml/web but I am not using Spring boot.

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

The application is deployed on apache-tomcat-8.0.30, and I also tried apache-tomcat-7.0.37.

推荐答案

我找到了答案.初始化上下文时,过滤器未正确注册,因此出现上述奇怪的行为.

I have found the answer. When initialising the context, Filters were not registered properly so the wierd behaviour described above.

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

The solution was to create a class as follows

public class SecurityInitialiser extends SecurityWebApplicationInitializer(){}

并从 WebInitialiser 类中删除 onStartup 方法.

and remove the onStartup method from the WebInitialiser class.

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

The reason this works in Spring boot it's because Filters are scanned and registered automatically.

这篇关于Spring Saml FilterChainProxy 清除上下文 - null 身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 06:44