Reputation: 26874
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?
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
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
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