【问题标题】:Spring Security 3.2 CSRF disable for specific URLsSpring Security 3.2 CSRF 禁用特定 URL
【发布时间】:2014-04-26 19:06:45
【问题描述】:

使用 Spring security 3.2 在我的 Spring MVC 应用程序中启用 CSRF。

我的 spring-security.xml

<http>
 <intercept-url pattern="/**/verify"  requires-channel="https"/>
 <intercept-url pattern="/**/login*"  requires-channel="http"/>
 ...
 ...
 <csrf />
</http>

尝试为请求 URL 中包含“验证”的请求禁用 CSRF。

MySecurityConfig.java

@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

private CsrfMatcher csrfRequestMatcher = new CsrfMatcher();

@Override
public void configure(HttpSecurity http) throws Exception {

    http.csrf().requireCsrfProtectionMatcher(csrfRequestMatcher);

}

class CsrfMatcher implements RequestMatcher {
    @Override
    public boolean matches(HttpServletRequest request) {

        if (request.getRequestURL().indexOf("verify") != -1)
            return false;
        else if (request.getRequestURL().indexOf("homePage") != -1)         
            return false;

        return true;
    }
}

}

Csrf 过滤器验证从“验证”提交的 CSRF 令牌,并在我从 http 向 https 提交请求时抛出无效令牌异常 (403)。在这种情况下如何禁用 csrf 令牌身份验证?

【问题讨论】:

  • 在我们尝试解决此问题之前,您为什么要使用 XML 和 JavaConfig?这可能会给您带来诸如我不确定哪个配置优先等问题。您应该选择其中之一。
  • 使用 XML 配置将一些 URL 引导至 https,将其他 URL 引导至 http。在 XML 中添加了 CSRF 功能,但是当用户从通过 https 引导的页面提交请求时,我们遇到了问题(无效令牌)。 1. 用户登陆 http 上的页面(主页) 2. 导航到 https 上的页面(验证) 3. 从验证页面提交请求时获取 Invalid Token 异常。所以尝试在验证页面上禁用 CSRF 身份验证。
  • 您可以使用 java 配置 http.requiresChannel() 通过 Java 配置启用通道安全性。不要同时使用 XML 和 JavaConfig 使用其中之一。我的猜测是您的 Security Java Configuraiton 没有被 XML 配置拾取或覆盖
  • 这是一篇关于如何使用 xml 配置禁用某些 URL 的 CSRF 检查的完整博客:blogs.sourceallies.com/2014/04/… 不幸的是,它似乎不适用于我的 Spring Security 3.2 版本.8.

标签: spring spring-mvc spring-security


【解决方案1】:

我知道这不是一个直接的答案,但人们(如我)在搜索这类问题时通常不会指定 spring 的版本。 所以,自从 spring security a method exists 让我们忽略一些路由:

以下将确保 CSRF 保护被忽略:

  1. 任何 GET、HEAD、TRACE、OPTIONS(这是默认设置)
  2. 我们还明确声明忽略任何以“/sockjs/”开头的请求
http .csrf() .ignoringAntMatchers("/sockjs/**") 。和() ...

【讨论】:

  • 在 Spring Boot 2.1.4 和 Spring Security 5.1.5 上仍然可以正常工作
  • 可以使用 Spring Security 5.20 和 Spring MVC 5.2.0 进行验证
【解决方案2】:

我希望我的回答可以帮助别人。我在搜索 How to disable CSFR for specific URLs in Spring Boot 时发现了这个问题。

我使用了这里描述的解决方案: http://blog.netgloo.com/2014/09/28/spring-boot-enable-the-csrf-check-selectively-only-for-some-requests/

这是允许我在某些 URL 上禁用 CSFR 控件的 Spring Security 配置:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    // Build the request matcher for CSFR protection
    RequestMatcher csrfRequestMatcher = new RequestMatcher() {

      // Disable CSFR protection on the following urls:
      private AntPathRequestMatcher[] requestMatchers = {
          new AntPathRequestMatcher("/login"),
          new AntPathRequestMatcher("/logout"),
          new AntPathRequestMatcher("/verify/**")
      };

      @Override
      public boolean matches(HttpServletRequest request) {
        // If the request match one url the CSFR protection will be disabled
        for (AntPathRequestMatcher rm : requestMatchers) {
          if (rm.matches(request)) { return false; }
        }
        return true;
      } // method matches

    }; // new RequestMatcher

    // Set security configurations
    http
      // Disable the csrf protection on some request matches
      .csrf()
        .requireCsrfProtectionMatcher(csrfRequestMatcher)
        .and()
      // Other configurations for the http object
      // ...

    return;
  } // method configure


  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) 
      throws Exception {

    // Authentication manager configuration  
    // ...

  }

}

它适用于 Spring Boot 1.2.2(和 Spring Security 3.2.6)。

【讨论】:

  • @amit 是的,它对我有用。但我也允许所有 GET 请求,如参考中的示例。我现在也更新了我的答案。
【解决方案3】:

我正在使用 Spring Security v4.1。经过大量阅读和测试,我使用 XML 配置禁用了特定 URL 的 CSRF 安全功能。

<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <http pattern="/files/**" security="none" create-session="stateless"/>

    <http>
        <intercept-url pattern="/admin/**" access="hasAuthority('GenericUser')" />
        <intercept-url pattern="/**" access="permitAll" />
        <form-login 
            login-page="/login" 
            login-processing-url="/login"
            authentication-failure-url="/login"
            default-target-url="/admin/"
            password-parameter="password"
            username-parameter="username"
        />
        <logout delete-cookies="JSESSIONID" logout-success-url="/login" logout-url="/admin/logout" />
        <http-basic />
        <csrf request-matcher-ref="csrfMatcher"/>
    </http>

    <beans:bean id="csrfMatcher" class="org.springframework.security.web.util.matcher.OrRequestMatcher">
        <beans:constructor-arg>
            <util:list value-type="org.springframework.security.web.util.matcher.RequestMatcher">
                <beans:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                    <beans:constructor-arg name="pattern" value="/rest/**"/>
                    <beans:constructor-arg name="httpMethod" value="POST"/>
                </beans:bean>
                <beans:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                    <beans:constructor-arg name="pattern" value="/rest/**"/>
                    <beans:constructor-arg name="httpMethod" value="PUT"/>
                </beans:bean>
                <beans:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                    <beans:constructor-arg name="pattern" value="/rest/**"/>
                    <beans:constructor-arg name="httpMethod" value="DELETE"/>
                </beans:bean>
            </util:list>
        </beans:constructor-arg>
    </beans:bean>

    //...

</beans:bean>

通过上述配置,我仅为所有以/rest/开头的URL的POST|PUT|DELETE请求启用CSRF安全。

【讨论】:

    【解决方案4】:

    明确禁用特定 url 模式并启用某些 url 模式。

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @EnableWebSecurity
    public class SecurityConfig {
    
        @Configuration
        @Order
        public static class GeneralWebSecurityConfig extends WebSecurityConfigurerAdapter {
            
            
            protected void configure(HttpSecurity http) throws Exception {
                http.csrf().ignoringAntMatchers("/rest/**").and()
                .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/home/**","/search/**","/geo/**").authenticated().and().csrf()
                .and().formLogin().loginPage("/login")
                .usernameParameter("username").passwordParameter("password")
                .and().exceptionHandling().accessDeniedPage("/error")
                .and().sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true);
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      这条简单的线暂时可以派上用场:

      <http pattern="/home/test**" security="none" />
      

      【讨论】:

      • security='none' 属性的唯一问题是 完全 从此 url 禁用 spring-security。
      【解决方案6】:
      <http ...>
          <csrf request-matcher-ref="csrfMatcher"/>
      
          <headers>
              <frame-options policy="SAMEORIGIN"/>
          </headers>
      
          ...
      </http>
      
      <b:bean id="csrfMatcher"
          class="AndRequestMatcher">
          <b:constructor-arg value="#{T(org.springframework.security.web.csrf.CsrfFilter).DEFAULT_CSRF_MATCHER}"/>
          <b:constructor-arg>
              <b:bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
                <b:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                  <b:constructor-arg value="/chat/**"/>
                </b:bean>
              </b:bean>
          </b:constructor-arg>
      </b:bean>
      

      平均数

       http
              .csrf()
                  // ignore our stomp endpoints since they are protected using Stomp headers
                  .ignoringAntMatchers("/chat/**")
      

      示例来自: https://docs.spring.io/spring-security/site/docs/4.1.x/reference/htmlsingle/

      【讨论】:

      • 你忘记在 NegatedRequestMatcher 和 AntPathRequestMatcher 之间封装一个构造函数
      【解决方案7】:

      使用安全=“无”。 例如在 spring-security-config.xml 中

      <security:intercept-url pattern="/*/verify" security="none" />
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-09
        • 2015-06-14
        • 2014-09-30
        • 2018-12-12
        • 2018-11-22
        • 2015-09-27
        相关资源
        最近更新 更多