Spring Security: enable / disable CSRF by client type (browser / non-browser )
Solution 1
I am sure there is a way to do this in Spring Security XML, but since I am using Java Config, here is my solution.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Configuration
@Order(1)
public static class SoapApiConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/soap/**")
.csrf().disable()
.httpBasic();
}
}
@Configuration
public static class WebApiConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginProcessingUrl("/authentication")
.usernameParameter("j_username")
.passwordParameter("j_password").permitAll()
.and()
.csrf().disable()
}
}
}
Solution 2
IMHO, there is nothing like that out of the box. What I would do in your case, is to have a hierarchy of URL for example rooted at /api
that would be exempt of csrf. It is easy to configure. In the XML config, you have a normal <http>
block including <csrf/>
, you just duplicate it and modify the first block like that
<http pattern="/api/**">
...
<!-- csrf -->
</http>
As it is first, it will be triggered for any request to /api
hierachy without using csrf, and all other requests will use it.
In the normal part of the application, you never use the /api/**
url, and reserve them to non-browser usages.
Then in your controllers, you map them to both their normal url and a copy under /api
:
@Controller
@RequestMapping({ "/rootcontrollerurl", "/api/rootcontrollerurl"})
class XController {
@RequestMapping(value = "/request_part_url", ...)
public ModelAndView method() {
...
}
}
(of course, rootcontrollerurl
and request_part_url
may be blank ...)
But you must analyze the security implication of allowing non csrf controlled requests, and eventually exclude controllers from the /api
hierarchy.
Solution 3
Here is what I used to disable the CSRF protection on an specific endpoint on your appconfig-security.xml add a node with the information of your pattern like the following example:
<http security="none" pattern="/sku/*"/>
<http security="none" pattern="/sku/*/*"/>
<http security="none" pattern="/sku"/>
Just keep in mind the order is important if you are going to use map all request using the symbol '*' goes first.
Related videos on Youtube
Himalay Majumdar
Updated on June 07, 2022Comments
-
Himalay Majumdar about 2 years
Spring Security documentation says:
"When you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection."
What if my service is going to be used by both "browser" and "non-browser" clients such as third party external services, does Spring Security provide a way to disable CSRF exclusively for certain type of clients?-
Neil McGuigan over 9 yearsI would just put a flash program in a browser page, say I'm a non-browser client, and attack the user when they have no CSRF protection.
-
Himalay Majumdar over 9 years@NeilMcGuigan I am disabling CSRF for trusted clients only, that trust I am establishing thru X509 and SSL/TLS.
-
-
Amit about 9 yearsAren't you disabling csrf for all the requests ?
-
Amit about 9 yearsAs soon as I disable csrf for one url it is disabled for all the urls
-
Himalay Majumdar about 9 years@amit Yes the above example disables csrf for all the requests, but you can selectively remove the explicit
csrf().disable()
from your configuration. My example is to demo enable/disable csrf for soap(which has typically non browser client) and rest (which usually serve browser clients). -
Himalay Majumdar about 9 yearsYour usecase is more fine grained where you want to enable/disable csrf at request level. I think spring would allow that using .antMatcher if you go thru spring official documents. Please let us know if you find something. else I will do some research over the weekend and let you know.
-
Amit about 9 yearsI am also thinking for the browser and non browser use case.. say for example I want all the requests to /webpages/browser csrf enabled and everything else csrf disable. can we achieve it from your example. I tried but either csrf is disabled for all or enabled for all.. Sure will share if I make any progress...
-
Amit about 9 yearsPlease see my question stackoverflow.com/questions/30498328/…