Spring SAML扩展和Spring Security CSRF保护冲突
我们有一个带有Spring Security(3.2.4)的Spring
MVC(4.0.5)应用程序,其中包含可以正常工作的CSRF保护。现在,我们添加了SAML安全扩展(spring-security-saml2-core
1.0.0),该扩展引起CSRF保护问题。
元数据已在SSOCircle上进行了配置,并尝试直接访问SSOCircle
http://localhost:8080/myapp
上的登录页面。身份验证后,浏览器将重定向到http://localhost:8080/myapp/saml/SSO
并生成错误:
如果我们关闭CSRF保护,则一切正常。我们如何维护CSRF保护并仍使用SAML扩展?
在设置SAML扩展之前,我们使用了登录表单,并且CSRF保护有效,并且在登录JSP上没有收到错误,并且它没有令牌。
SAML之前的代码:
@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.antMatchers("/login", "/login.request", "/logout").permitAll()
.anyRequest()
.hasAnyAuthority("MyRole")
.and().formLogin()
.loginPage("/login.request").loginProcessingUrl("/login")
.failureUrl("/login.request?error").permitAll().and().logout()
.logoutUrl("/logout").permitAll()
.logoutSuccessUrl("/login.request");
}
使用SAML的代码:
@Overrideprotected void configure(HttpSecurity http) throws Exception {
//http.csrf().disable();
http.httpBasic().authenticationEntryPoint(samlEntryPoint());
http.addFilterBefore(metadataGeneratorFilter(),
ChannelProcessingFilter.class).addFilterAfter(samlFilter(),
BasicAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/error").permitAll()
.antMatchers("/saml/**").permitAll()
.anyRequest()
.hasAnyAuthority("MyRole")
.anyRequest().authenticated();
http.logout().logoutSuccessUrl("/");
}
重新启用CSRF保护并将日志记录设置为DEBUG后,以下是成功认证之后立即发生的日志:
22.10.2014 16:54:17.374 [http-bio-8080-exec-8] DEBUG o.s.w.m.support.MultipartFilter - Using MultipartResolver 'filterMultipartResolver' for MultipartFilter
22.10.2014 16:54:17.377 [http-bio-8080-exec-8] DEBUG o.s.b.f.s.DefaultListableBeanFactory -
Returning cached instance of singleton bean 'filterMultipartResolver'
22.10.2014 16:54:17.788 [http-bio-8080-exec-8] DEBUG o.s.w.m.support.MultipartFilter -
Request [/epass/saml/SSO] is not a multipart request
22.10.2014 16:54:17.790 [http-bio-8080-exec-8] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/saml/sso'; against '/resources/**'
22.10.2014 16:54:17.791 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
/saml/SSO at position 1 of 14 in additional filter chain; firing Filter: 'MetadataGeneratorFilter'
22.10.2014 16:54:17.793 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
/saml/SSO at position 2 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
22.10.2014 16:54:17.795 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
/saml/SSO at position 3 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
22.10.2014 16:54:17.797 [http-bio-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
HttpSession returned null object for SPRING_SECURITY_CONTEXT
22.10.2014 16:54:17.798 [http-bio-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@b08c9c9. A new one will be created.
22.10.2014 16:54:17.800 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
/saml/SSO at position 4 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
22.10.2014 16:54:17.801 [http-bio-8080-exec-8] DEBUG o.s.s.w.h.writers.HstsHeaderWriter -
Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@244a79ef
22.10.2014 16:54:17.802 [http-bio-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy -
/saml/SSO at position 5 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
22.10.2014 16:54:17.805 [http-bio-8080-exec-8] DEBUG o.s.security.web.csrf.CsrfFilter -
Invalid CSRF token found for `http://localhost:8080/myapp/saml/SSO`
22.10.2014 16:54:17.807 [http-bio-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
22.10.2014 16:54:17.808 [http-bio-8080-exec-8] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter -
SecurityContextHolder now cleared, as request processing completed
回答:
您至少有两个选择。
一种是实现自定义RequestMatcher
(org.springframework.security.web.util.RequestMatcher
),该自定义()在Spring
SAML URL上将不匹配,并将其通过以下方式提供给csrf配置:
http.csrf().requireCsrfProtectionMatcher(matcher);
另一个更简单的方法是在单独的http配置中定义Spring SAML端点,该配置不会启用csrf保护。
用于执行此操作的XML配置可以类似于:
<!-- SAML processing endpoints --><security:http pattern="/saml/**" entry-point-ref="samlEntryPoint">
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
<security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
</security:http>
<!-- Secured pages with SAML as entry point -->
<security:http entry-point-ref="samlEntryPoint">
<security:csrf />
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
</security:http>
对于Java配置,这样的方法应该起作用:
@Configuration@EnableWebSecurity
public class MutlipleHttpConfigurationConfig {
@Configuration
@Order(1)
public static class SAMLWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/saml/**");
http.csrf().disable();
http.httpBasic().authenticationEntryPoint(samlEntryPoint());
http.addFilterBefore(metadataGeneratorFilter(),
ChannelProcessingFilter.class).addFilterAfter(samlFilter(),
BasicAuthenticationFilter.class);
}
}
@Configuration
public static class BasicWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().authenticationEntryPoint(samlEntryPoint());
http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class);
http
.authorizeRequests()
.antMatchers("/error").permitAll()
.anyRequest()
.hasAnyAuthority("MyRole")
.anyRequest().authenticated();
http.logout().logoutSuccessUrl("/");
}
}
}
可以在Spring Security手册中找到有关使用Java配置定义多个http配置的详细信息。
以上是 Spring SAML扩展和Spring Security CSRF保护冲突 的全部内容, 来源链接: utcz.com/qa/417041.html