Spring Boot starter with custom filter in default Spring Security filter chain - spring-boot

Working on a shared Spring Boot security starer for my microservices.
I would like this starter to automatically add a custom filter to a default Spring Security filer chain, so consumers won't have to repeat definition of this custom filter every time they build their SecurityFilterChains.
How can I achieve this?
I have implemented a simple filter: class MyAuthenticationFilter extends OncePerRequestFilter
And the only way I am aware of for enabling the filter is: using addFilterBefore/addFilterAfter on org.springframework.security.config.annotation.web.builders.HttpSecurity.
This a perfect place to add custom security filter when you configure a single app, but not for making a starter with custom defaults. If I try to use HttpSecurity#addFilterBefore and build SecurityFilterChain #Bean in my starter, this will not work as expected. Consumer of the starter will want to configure their own SecurityFilterChain to define their own paths they want to secure, which will simply "shadow" the filter chain defined in the starter (there will be 2 filter chains - one from starer and another one from starter's consumer). HTTP requests will be simply refused by consumer's filter chain with default set of security filters and will never reach filter chain of the starter, where custom filter is defined.
So, what is the right extension point from Spring, which I should use to add my custom filter to the list of default filters? (for ANY filter chain consumer would want to build further with HttpSecurityBuilder DSL)

Related

shiro custom filter conflict spring filter

enter image description here
shiro anon lose efficacy
if I NOT use #bean Filter ,Filter---->service is null
How Can I use custom filter shiro anon is use and filter inside service is not null
I checked your image of your code, and I was unable to find the service object which is null.
I've already set up a project which integrates Apache Shiro + Spring, which may be helpful.

Apply #PostFilter / #PostAuthorize for all endpoints

I have been able to use #PostFilter / #PostAuthorize successfully as follows:
#RestController
public class MyController{
#PostFilter("hasPermission(filterObject, 'blah')")
public List<MyObject> getIt();
}
However, what I would like to do is configure the hasPermission (or some similar) check on all endpoints in my application. In other words, doing something like a Spring Security Fitler but using the domain object prior to it being marshalled in the HttpServletResponse. I would prefer not to use a Filter because of the marshalling / unmarshalling aspect especially when doing filtering (#PostFilter) as it changes the result.
The idea is that I would like this filtering behavior to be a cross-cutting security concern and therefore not have to remember to add it to each endpoint as it is added. This would also allow me to do testing of this filtering once for the application instead of for each endpoint.

Configure Spring HTTP Security at Runtime

All http security is applied at startup:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
}
During runtime, I am trying to add more to it ...
applicationContext.getBean(WebSecurityConfigurerAdapter).http.authorizeRequests().antMatchers("bla").hasRole("admin")
When that line is executed, it adds it to http.authorizeRequests()'s but /bla is still accessible by "non admins"
When server is restarted, this change takes effect because it is loading bla from the database.
How do I make the security take effect instantly without restarting the server?
You are trying to dynamicaly change a spring bean at runtime which is very hard to do unless you use tools like spring-loaded or JRebel.
There is a lot of SO about it :
Update spring beans dynamically. Is it possible?
dynamically change spring beans
Can I replace a Spring bean definition at runtime?
The best approach (in my opinion) for your use case is to use spring profiles.
Define a bean with authorisations for /bla and another bean without. Then use them in different profiles.
see dynamically declare beans at runtime in Spring
My solution to these case scenarios is to make a dynamic custom spring security rule to match with all the path.
http
.authorizeRequests()
.antMatchers("/**").access("#customSecurityRule.check(authentication)");
This way new endpoint will automatically be configured with our custom security rule, and in our custom security rule we can preety much do anything we want, checking their roles, validate it againts our database and etc.

Wiring in spring-session without using AbstractHttpSessionApplicationInitializer or web.xml?

So I have an existing internal application framework which only requires consuming applications to register a single filter in their web.xml - a DelegatingFilterProxy which references a CompositeFilter. As part of that CompositeFilter we have a whole slew of other filters in a specific order (some custom, springSecurityFilterChain, etc).
I now want to bring spring-session into the mix but I don't want to use the WebApplicationInitializer (I need to support servlet 2.5 containers) nor do I want to have to have every application modify their web.xml. I'd want to provide it as part of our internal framework and simply throw the springSessionRepositoryFilter into our CompositeFilter. Seems simple enough - but it seems that no matter which position I put it in (we currently have 11 or so other filters in there) things just don't seem to work. Our authentication seems to break and things just don't work. All does work fine if I do manually add the springSessionRepositoryFilter directly to web.xml - so I'm confused. Any help?
I figured it out. The SessionRepositoryFilter has to come before the RequestContextFilter in the filter chain. Also have to make sure to turn off disable url rewriting in Spring security, since the springSecurityFilterChain will come after the SessionRepositoryFilter. If you don't then the re-writing of the URLs with the _s parameter won't work.

Spring security - implement oauth with existing FilterChainProxy

we have existing web application built with Spring security 3.1 ,Wink(for rest)
we now need to add oauth2 (client_credentials flow) for several resources, i looked into many examples and all of them using the Http namespace configuration along with spring dispatcher servlet (which we didn't have till now)
problem is that http namespace is creating a springSecurityFilterChain which we already had in the application , so first thing i renamed the existing filter so the default could co-exist with the old one.
but this does not work, its either the existing chain working for requests or the new one.
i have tried the following already
1. disabled dispatcher servlet context by giving empty config location (in web.xml)
2. tried to have the oauth configuration in application-context.xml (right to the existing FilterChainProxy)
3. Allow the /oauth/token in existing chain by setting its filter to none (so the new can take over)
4. tried to declare the oauth filters in the existing chain but there was a problem with its not getting the right clientAuthentication
i really don't know what else to try - so the question is : is it possible to have both declared in the same webapp ? or is it possible to declare oauth2 configuration in the old fashion.
thanks
Shlomi
I managed to do that eventually, having the API (protected with oauth) completey separated url from the rest of the application.
so the Http namespace is creating the springSecurityFilterChain bean and the others just have different bean names. everyone is delegated through the DelegatingProxy in web.xml
i needed to puth the API URL prefix in other chains and allow all requests through , leaving the oauth security chanin to deal with security.
(i.e filter-chain pattern="/api/**" filters="none)
regarding the spring oauth2 bounded to spring MVC so tight i think is not a good implementation.
the mapping of the dispatcher servlet cannot be for /* but have to be something like /auth/*
so a special filter inherit from ClientCredentialsTokenEndpointFilter with special path like super("/auth/oauth/token") was needed.
it also cannot be /api/* since this is the real API URI mapped by our rest framework (wink RestServlet)
so we have something like this
http://server:port/context/auth/oauth/token
http://server:port/context/api/someresource (protected with oauth2)
http://server:port/context/rest/someresource (old rest for application)
Shlomi

Resources