首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring扩展与Spring安全CSRF保护冲突

Spring扩展与Spring安全CSRF保护冲突
EN

Stack Overflow用户
提问于 2014-10-22 13:39:38
回答 4查看 8.3K关注 0票数 10

我们有一个Spring (4.0.5)应用程序和Security (3.2.4),其中包含了工作良好的CSRF保护。我们现在正在添加SAML安全扩展(spring-security-saml2-core 1.0.0),这将导致CSRF保护问题。

元数据已在SSOCircle上配置,并试图访问http://localhost:8080/myapp指向SSOCircle上的登录页面。身份验证之后,浏览器重定向到http://localhost:8080/myapp/saml/SSO并生成一个错误:

HTTP状态403 -未找到预期的CSRF令牌。您的会话到期了吗?

如果我们关掉CSRF保护,一切都正常。我们如何维护CSRF保护,并仍然使用SAML扩展?

在设置SAML扩展之前,我们使用了一个登录表单,CSRF保护起作用了,在登录JSP上没有收到错误,而且它没有令牌。

SAML之前的代码:

代码语言:javascript
复制
@Override
protected 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代码:

代码语言:javascript
复制
@Override
protected 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保护并将日志设置为调试之后,以下是成功身份验证后立即发生的日志:

代码语言:javascript
复制
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
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-10-25 08:06:33

你至少有两个选择。

一个是实现一个自定义RequestMatcher (org.springframework.security.web.util.RequestMatcher),它将与Spring不匹配,并将其提供给csrf配置:

代码语言:javascript
复制
http.csrf().requireCsrfProtectionMatcher(matcher);

另一个更容易的方法是在单独的http配置中定义Spring端点,该配置将不启用csrf保护。

这样做的XML配置可以类似于:

代码语言:javascript
复制
<!-- 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配置,这样的配置应该可以工作:

代码语言:javascript
复制
@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("/");
        }
    }
}

有关用Java定义多个http配置的详细信息,可以在弹簧安全手册中找到。

票数 11
EN

Stack Overflow用户

发布于 2016-11-03 15:15:29

这对我来说很管用:

http.csrf().ignoringAntMatchers("/saml/**") ...

因此,在处理/saml/**时禁用CSRF。

来自:https://github.com/choonchernlim/spring-security-adfs-saml2/blob/master/src/main/java/com/github/choonchernlim/security/adfs/saml2/SAMLWebSecurityConfigurerAdapter.java

票数 9
EN

Stack Overflow用户

发布于 2014-10-27 16:29:45

对于其他可能面临这个问题的人,我也能够通过强制执行过滤器的顺序来解决这个问题。

我换了这个:

代码语言:javascript
复制
http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
    .addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);

在这方面:

代码语言:javascript
复制
FilterChainProxy samlFilter = samlFilter();

http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
    .addFilterAfter(samlFilter, BasicAuthenticationFilter.class)
    .addFilterBefore(samlFilter, CsrfFilter.class);

现在起作用了。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26508835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档