问题描述
我遇到了与 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-core
库 1.0.2.RELEASE
与 spring
4.3 结合使用.0.RELEASE
和 spring-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 身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!