Spring Security 3.2 CSRF 禁用特定 URL

Posted

技术标签:

【中文标题】Spring Security 3.2 CSRF 禁用特定 URL【英文标题】:Spring Security 3.2 CSRF disable for specific URLs 【发布时间】: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. 【参考方案1】:

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

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

    任何 GET、HEAD、TRACE、OPTIONS(这是默认设置) 我们还明确声明忽略任何以“/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" />

【讨论】:

以上是关于Spring Security 3.2 CSRF 禁用特定 URL的主要内容,如果未能解决你的问题,请参考以下文章

在 spring-security 中更改 csrf 令牌

spring security4.2 配置CSRF防御场景

使用 Spring Security 的 CSRF 保护

使用 Spring Security 的 CSRF 保护

在 Spring Security 中启用 CSRF 时,访问被拒绝 403

Spring-Security对CSRF攻击的支持