Hello,
currently i have a small app that has 2 controllers, one for a rest like api and one for basic web stuff.
for the web stuff i use spring security for login, here i want CSRF check enabled, but for the rest api i dont need/want CSRF protection.
is there a way to disable the CSRF protection only for the Api controller or the /api/* request pattern but have it enabled for everything else?
all i found yet is to disable CSRF at all.
Thanks in Advance
PS: I'm using spring-boot 0.5.0.BUILD-SNAPSHOT
The security.enable_csrf
configuration setting only applies to the resources which are protected by SecurityAutoConfiguration
(/**
by default, but I assume you have your own configuration for your own resources). You should be able to configure CSRF protection per filter chain using your own WebSecurityConfigurerAdapter
. Maybe if you can share your code we can look at the problem and make more specific recommendations?
Thank you for your fast reply :)
where can i change the /**
or at least add some excludes to it?
this is my current WebSecurityConfig.java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// Dis able CSRF
// TODO find a way to allow CSRF for everything but API
http.csrf().disable();
// System stuff
http.authorizeRequests()//
.antMatchers("/favicon.ico").permitAll();
// Pages
http.authorizeRequests()//
.antMatchers("/v1/**").permitAll()//
.antMatchers("/v2/**").permitAll()//
.antMatchers("/v3/**").permitAll()//
.antMatchers("/v4/**").permitAll()//
.antMatchers("/v5/**").permitAll()//
// disallow everything else...
.anyRequest().authenticated();
http.formLogin()//
.defaultSuccessUrl("/admin/news")//
.loginPage("/login")//
.permitAll();
http.logout().permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
// cut
}
}
If you use @EnableWebSecurity
you switch off the Spring Boot settings completely, so really this is a vanilla Security question. You could probably get help on Stackoverflow.
What you will need is 2 WebSecurityConfigurerAdapters
, one with your /api/**
endpoints and one with lower priority (higher @Order
) to protect the rest. Disable the csrf protection in one and not the other.
hmm, i really love the black magic behind spring but sometimes it is very confusing.
i don't yet understand why @EnableWebSecurity
disables Spring Boot settings. i got my WebSecurityConfig
from this guide http://spring.io/guides/gs/securing-web/.
i just found https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/spring-boot-sample-secure/src/main/java/org/springframework/boot/sample/ops/ui/SampleSecureApplication.java which i think then is the Spring Boot way to configure?
there it is
@Bean
public ApplicationSecurity applicationSecurity() {
return new ApplicationSecurity();
}
@Order(Ordered.LOWEST_PRECEDENCE - 8)
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
.loginPage("/login").failureUrl("/login?error").permitAll();
}
}
so when i remove the @EnableWebSecurity
and return my WebSecurityConfig
in applicationSecurity()
and add another Bean with a WebSecurityConfigurerAdapter for my api how i would tell the one for api to ignore csrf? would it be enough to have the http.csrf().disable();
?
Thanks! :)
okay, i tested that.
as soon as i have http.csrf().disable();
in one of the WebSecurityConfigurerAdapter
beans it disables CSRF for all :(
next test is the http.csrf().requireCsrfProtectionMatcher(RequestMatcher matcher);
i just found.
this snipped works for me.
http.csrf().requireCsrfProtectionMatcher(new RequestMatcher() {
private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
private RegexRequestMatcher apiMatcher = new RegexRequestMatcher("/v[0-9]*/.*", null);
@Override
public boolean matches(HttpServletRequest request) {
// No CSRF due to allowedMethod
if(allowedMethods.matcher(request.getMethod()).matches())
return false;
// No CSRF due to api call
if(apiMatcher.matches(request))
return false;
// CSRF for everything else that is not an API call or an allowedMethod
return true;
}
});
Looks like csrf settings are global in Spring Security. Oh well.
/cc @rwinch
Was there something else needed @philwebb or was this more of an FYI?
@dodgex One thing I would suggest is avoiding anonymous inner classes within the configuration because they will have references to the configuration objects. Since the anonymous inner class is used by your application there is going to continue to be a reference to the anonymous inner class. In turn this means that the Configuration will still have a reference to it and will not be able to be garbage collected. Instead consider using a static inner class or use the existing RequestMatchers which can be use to do what you want.
@rwinch Just an FYI in case you were interested. Sorry, should have put that in the /cc comment.
@philwebb Thank you for the cc ;-)
@rwinch First of all thank you for the hint regarding the inner class and the related memory leak. i didn't knew that, although it is somehow obvious.
i'll take a look on the existing matchers if there is one that does what i need, otherwise i keep my own matcher but as a static inner class.
Thank you both! :+1:
For now i'll keep my RequestMatcher (but as a static class) as i didn't found an existing Matcher that i could use for my case.
Thanks a lot for the working snippet :)
FYI...Spring Security 4.0 added ignoringAntMatchers:
csrf()
.ignoringAntMatchers("/nocsrf","/ignore/startswith/**")
yep, and we have to use 1.3.0.M1 version of spring-boot, because 1.2.5 do not contain this method.
If you use xml for security configurations you can add -
<http security="none" pattern="/pathWhereCSRFWillBeIgnored/**"/>
what is xml equalent of
csrf()
.ignoringAntMatchers("/nocsrf","/ignore/startswith/**")
?
That鈥檚 a usage question about a different project (appended to a closed issue). Please ask questions in stack overflow.
How can we bypass GET type URL by using:
csrf()
.ignoringAntMatchers("/nocsrf","/ignore/startswith/**") in spring-security 4 or 5
@amitrathi1982 have you seen the comment jut before yours? Please ask questions on Stackoverflow.
Most helpful comment
FYI...Spring Security 4.0 added ignoringAntMatchers: