Reputation: 125
As a solutions architect, I want to add a filter to all spring security filter chains in the current application context, regardless of how or where they are declared, so that this filter cannot be missed by a developer who forgot to add it.
Suppose that different developers are adding in some custom security to address different logical concerns specific to their filter. There can be 1 or more WebSecurityConfigurerAdapters
public class DeveloperWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.mvcMatcher("/forgottenFilter/**")
//.addFilter(reallyImportantFilter)
.authorizeRequests()
.anyRequest().access("developerDefinedCriteria");
}
}
I myself could declare a WebSecurityConfigurerAdapter that adds a filter to the HttpSecurity, but this is treated as an individual catch-all filter chain.
public class FrameworkWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
Filter reallyImportantFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilter(reallyImportantFilter);
}
}
In effect, I have not added my filter to the developer's chain, but rather created an entirely separate chain that interferes with the mapping of other filter chains.
DefaultSecurityFilterChain INFO: Creating filter chain: any request, [... ReallyImportantFilter@77ce8bc5 ...]
DefaultSecurityFilterChain INFO: Creating filter chain: Mvc [pattern='/forgottenFilter/**'] [...]
Is there an out of the box way to configure such a filter? If not, what patterns can be applied to avoid a filter from being forgotten?
Upvotes: 0
Views: 1304
Reputation: 2644
You can create a generic filter and register it in the servlet context. Here is a sample code for your reference:
public class ReallyImportantFilter extends GenericFilterBean {
private static final Logger LOGGER = LoggerFactory.getLogger(ReallyImportantFilter.class);
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) {
try {
chain.doFilter(request, response);
} catch (final Throwable t) {
LOGGER.error("Encountered unhandled exception.", t);
final HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
Register this filter and assign appropriate order precedence.
<bean id="reallyImportantFilterRegistration" class="org.springframework.boot.web.servlet.FilterRegistrationBean">
<property name="filter">
<bean class="com.test.web.errorhandling.ReallyImportantFilter"/>
</property>
<property name="order">
<util:constant static-field="org.springframework.core.Ordered.HIGHEST_PRECEDENCE"/>
</property>
</bean>
Upvotes: 0
Reputation: 2220
A feature of WebSecurityConfigurerAdapter
came to mind. The javadoc states:
Will automatically apply the result of looking up AbstractHttpConfigurer from SpringFactoriesLoader to allow developers to extend the defaults. To do this, you must create a class that extends AbstractHttpConfigurer and then create a file in the classpath at "META-INF/spring.factories" that looks something like:
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyClassThatExtendsAbstractHttpConfigurer
For example, in your case, you can create your own implementation of AbstractHttpConfigurer
where you add the very important filter:
package sample;
// ...
public class CustomSecurityConfigurer<H extends HttpSecurityBuilder<H>>
extends AbstractHttpConfigurer<CustomSecurityConfigurer<H>, H> {
@Override
public void init(H http) { }
@Override
public void configure(H http) {
// add your own filter... for example:
http.addFilterAfter(new ImportantFilter(), LogoutFilter.class);
}
}
... and add this line to the spring.factories in the META-INF folder:
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer=sample.CustomSecurityConfigurer
In WebSecurityConfigurerAdapter
, this configurer is added to the "list" of configurers (think CsrfConfigurer
, LogoutConfigurer
, ...) that will build the HttpSecurity
, and ultimately the corresponding filter chain.
If you have multiple WebSecurityConfigurerAdapter
s, each one will apply this configurer, so you'll end up configuring every filter chain that's created from HttpSecurity
.
Upvotes: 3