usr-local-ΕΨΗΕΛΩΝ
usr-local-ΕΨΗΕΛΩΝ

Reputation: 26874

Disable CSRF protection by property

Spring security offers an XML way to configure CSRF protection by applying the <csrf /> tag into the <http> element configuration.

For development purposes, I want to occasionally switch off such protection. Normally I would edit my security-context.xml file and change to <csrf disabled="true">.

I tried to use an expression such as <csrf disabled="${someProperty:false}" /> but it's not valid because XML schema accepts only a raw boolean value.

I don't want to use an entire bean profile (for the entire <http> element) just for a single parameter that has to be switched on/off sometimes.

Any advice?

Additional info

In order to perform some unit testing with RESTClient against authenticated controllers (when I am too lazy to use JUnit with MockMvc) I both need to bypass form authentication (e.g. using <http-basic /> and instructing RESTClient on the credentials) and disable CSRF, otherwise all requests will be blocked for missing token.

My application is a WAR application and by design it uses XML configuration instead of code-based configuration

Upvotes: 2

Views: 2120

Answers (2)

andreas
andreas

Reputation: 985

Because I stumbled upon this Question with the same problem I'd like to complement Faizal Sidek's answer, because his answer removes the default matching of Spring security.

To keep the default behaviour when csrf is enabled you need to match the requests HTTP method like this:

Your custom request matcher:

package my.example;

import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.regex.Pattern;

public class CustomRequestMatcher implements RequestMatcher {

    private Pattern allowedMethods = Pattern.compile("^(GET|TRACE|HEAD||OPTIONS)$");

    private boolean enabled;

    public CustomRequestMatcher(boolean enabled) {
        this.enabled = enabled;
    }

    @Override
    public boolean matches(HttpServletRequest httpServletRequest) {
        return enabled && !allowedMethods.matcher(httpServletRequest.getMethod()).matches();
    }

}

Then use it in your security.xml:

<http ...>
    <csrf request-matcher-ref="requestMatcher"/>
</http>

<beans:bean id="requestMatcher" class="my.example.CustomRequestMatcher">
    <beans:constructor-arg value="${myproperty}" />
</beans:bean>

Now if you set "myproperty" to false csrf is disabled, but if "myproperty" is true the default behaviour is preserved.

Upvotes: 3

Faizal Sidek
Faizal Sidek

Reputation: 196

Use request-matcher-ref and create your own custom RequestMatcher.

<csrf token-repository-ref="csrfTokenRepository" request-matcher-ref="csrfRequestMatcher" />

Here is for spring bean definition:

   <spring:bean class="com.faizalsidek.security.CsrfRequestMatcher" id="csrfRequestMatcher" />
        <spring:bean class="org.springframework.security.web.csrf.CookieCsrfTokenRepository" id="csrfTokenRepository" />

Here is the custom CsrfRequestMatcher:

public class CsrfRequestMatcher implements RequestMatcher {

  /**
   * Enable CSRF flag.
   */
  @Value("${csrf.enabled}")
  private boolean csrfEnabled;

  @Override
  public final boolean matches(final HttpServletRequest request) {
    return csrfEnabled;
  }
}

Upvotes: 2

Related Questions