问题
In am working on a Spring Boot (1.3.2) application which just serves Spring MVC REST controllers that are consumed by a JavaScript single page app (deployed standalone, not inside the boot jar). The setup uses Spring Security, Spring Session and has CSRF protection enabled.
This works as expected for the JavaScript client. A login is done by a GET call with Basic Auth provided, the backend creates a session, returns a cookie and also provides the CSRF token in the response according to this blog post at https://spring.io/guides/tutorials/spring-security-and-angular-js/ (except that the custom filter is way more behind in the chain to obtain the correct token after the SessionManagementFilter
- which is not that relevant for this question I think).
Until here, everything works as intended pretty elegantly without any workarounds.
Now we also want to expose some of the interfaces for mobile/cli clients. These clients should be able to access a subset of the interfaces via Basic Auth. So the goal is to allow non-readonly calls (POST, PUT, DELETE) for these clients by just providing the credentials via Basic Auth. As they provide the credentials in their request, it is not neccessary for them to provide a CSRF token.
So my first idea was to look for some way to conditionally skip some filters (the csrf) if there was a successful authentication by the provided Basic Auth. It seems that the existing filters are not meant to be used in that way and this would also somehow violate the concept of Spring Security.
I then thought to have found a solution by using the concept explained in the Spring Security docs (http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#multiple-httpsecurity) that uses separate WebSecurityConfigurerAdapter
s as also described in Spring Boot web app w/ both session + CSRF & stateless Basic Auth w/o CSRF or
How can I configure spring security for multiple servlets?
So currently I have two WebSecurityConfigurerAdapter
s with different Orders and disjunct request matchers, both overriding configure(AuthenticationManagerBuilder auth)
and configure(HttpSecurity http)
. I therefore aliased the relevant REST controllers by using @RequestMapping({"/things", "/aliased/things"})
to be able to get separate security filter chains.
This works in a way that depending on the Path ("things" or "aliased/things") the according filter chain is used. But somehow this setup is still corrupt as I now can do a "login" on the regular path, which creates a session and with this session, I now can also call one of the second filter chain's path which now results in a correct authentication (probably due to the SecurityContextPersistenceFilter
) which authenticates me and allows non CSRF-protected calls to the interfaces on the chain which should be used by the mobile clients only.
This seems not to be the way to handle such a case. I am interested in finding hints how to handle that requirement - which in my opinion should be some common use case. Probably I was running way to far in the wrong direction with my experiments.
来源:https://stackoverflow.com/questions/35610345/multiple-spring-security-configurations-for-rest-via-basicauth-vs-session-with