51

Enabled CSRF in my Spring MVC application using Spring security 3.2.

My spring-security.xml

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

Trying to disable CSRF for requests that contain 'verify' in request URL.

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 filter validates CSRF token that is submitted from 'verify' and Invalid token exception (403) is thrown as I'm submitting request to https from http. How can I disable csrf token authentication in such a scenario ?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Mahesh
  • 511
  • 1
  • 4
  • 3
  • Before we try and troubleshoot this, Why are you using the XML and the JavaConfig? This may cause you such issues as I'm not sure which configuration is taking precedence. You should choose one or the other. – Rob Winch Mar 20 '14 at 13:40
  • Used XML configuration to channel some of URLs to https and others to http. Added CSRF feature in XML but we ran into a problem (Invalid Token) when user submits a request from a page that is channeled on https. 1. User lands on a page (home) on http 2. Navigates to a page (verify) that is on https 3. Gets the Invalid Token exception when request is submitted from verify page. So trying to disable CSRF authentication on verify page. – Mahesh Mar 20 '14 at 18:51
  • 1
    You can use the java config http.requiresChannel() to enable channel security with Java Configuration. Do not use both XML and JavaConfig use one or the other. My guess is that your Security Java Configuraiton is not being picked up or overridden by the XML configuration – Rob Winch Mar 21 '14 at 14:52
  • Here is a well-done blog about how to disable the CSRF-check for some URLs, using xml configuration: http://blogs.sourceallies.com/2014/04/customizing-csrf-protection-in-spring-security/ *Unfortunately it does not seem to work with my version Spring Security 3.2.8.* – yglodt Sep 22 '15 at 14:53

6 Answers6

70

I know this is not a direct answer, but people (as me) usually don't specify spring's version when searching for this kinds of questions. So, since spring security a method exists that lets ignore some routes:

The following will ensure CSRF protection ignores:

  1. Any GET, HEAD, TRACE, OPTIONS (this is the default)
  2. We also explicitly state to ignore any request that starts with "/sockjs/"
     http
         .csrf()
             .ignoringAntMatchers("/sockjs/**")
             .and()
         ...
le0diaz
  • 2,488
  • 24
  • 31
16

I hope that my answer can help someone else. I found this question searching for How to disable CSFR for specfic URLs in Spring Boot.

I used the solution described here: http://blog.netgloo.com/2014/09/28/spring-boot-enable-the-csrf-check-selectively-only-for-some-requests/

This is the Spring Security configuration that allow me to disable the CSFR control on some URLs:

@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  
    // ...

  }

}

It works with Spring Boot 1.2.2 (and Spring Security 3.2.6).

james
  • 1,035
  • 2
  • 14
  • 33
Andrea
  • 15,900
  • 18
  • 65
  • 84
12

I am using Spring Security v4.1. After a lot of reading and testing, I disable the CSRF security feature for specific URLs using XML configuration.

<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>

With the above configuration, I enable the CSRF security only for POST|PUT|DELETE requests of all URLs which start with /rest/.

1000111
  • 13,169
  • 2
  • 28
  • 37
Georgios Syngouroglou
  • 18,813
  • 9
  • 90
  • 92
9

Explicitly disable for specific url patterns and enable for some url patterns.

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);
        }
    }
}
blueDexter
  • 977
  • 11
  • 14
2
<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>

mean of

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

example from : https://docs.spring.io/spring-security/site/docs/4.1.x/reference/htmlsingle/

Vahap Gencdal
  • 1,900
  • 18
  • 17
-3

Use security="none". for e.g in spring-security-config.xml

<security:intercept-url pattern="/*/verify" security="none" />
user8462556
  • 369
  • 6
  • 13