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 ?
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:
- Any GET, HEAD, TRACE, OPTIONS (this is the default)
- We also explicitly state to ignore any request that starts with "/sockjs/"
http
.csrf()
.ignoringAntMatchers("/sockjs/**")
.and()
...
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).
I am using Spring Security v4.1. After a lot of reading and testing I disable the crcf 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 crcf security only for POST|PUT|DELETE requests of all urls which start with /rest/
.
Temporarily this simple line could be handy:
<http pattern="/home/test**" security="none" />
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 {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private CustomPasswordEncoder passwordEncoder;
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
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);
}
}
}
Use security="none".
for e.g in spring-security-config.xml
<security:intercept-url pattern="/*/verify" security="none" />