Add HttpSecurity.addFilterAt (#3809)

Fixes gh-3784
This commit is contained in:
Rob Winch 2016-04-13 15:01:25 -05:00 committed by Joe Grandja
parent 2ef3da1b47
commit a7fb6d2e58
3 changed files with 64 additions and 0 deletions

View File

@ -149,6 +149,23 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
put(filter, position + 1);
}
/**
* Registers a {@link Filter} to exist at a particular {@link Filter} position
* @param filter the {@link Filter} to register
* @param atFilter the {@link Filter} that is already registered and that
* {@code filter} should be placed at.
*/
public void registerAt(Class<? extends Filter> filter,
Class<? extends Filter> atFilter) {
Integer position = getOrder(atFilter);
if (position == null) {
throw new IllegalArgumentException(
"Cannot register after unregistered Filter " + atFilter);
}
put(filter, position);
}
/**
* Registers a {@link Filter} to exist before a particular {@link Filter} that is
* already registered.

View File

@ -1025,6 +1025,25 @@ public final class HttpSecurity extends
return this;
}
/**
* Adds the Filter at the location of the specified Filter class. For example, if you
* want the filter CustomFilter to be registered in the same position as
* {@link UsernamePasswordAuthenticationFilter}, you can invoke:
*
* <pre>
* addFilterAt(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
* </pre>
*
* @param filter the Filter to register
* @param atFilter the location of another {@link Filter} that is already registered
* (i.e. known) with Spring Security.
* @return the {@link HttpSecurity} for further customizations
*/
public HttpSecurity addFilterAt(Filter filter, Class<? extends Filter> atFilter) {
this.comparitor.registerAt(filter.getClass(), atFilter);
return addFilter(filter);
}
/**
* Allows specifying which {@link HttpServletRequest} instances this
* {@link HttpSecurity} will be invoked on. This method allows for easily invoking the

View File

@ -17,6 +17,7 @@ package org.springframework.security.config.annotation.web.configurers;
import java.io.IOException;
import javax.servlet.FilterChain
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -55,6 +56,7 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher
import org.springframework.web.filter.OncePerRequestFilter
import spock.lang.Ignore;
@ -127,7 +129,26 @@ public class NamespaceHttpCustomFilterTests extends BaseSpringSpec {
// if not, use addFilterBefore or addFilterAfter
.addFilter(new CustomFilter())
}
}
def "http/custom-filter@position at"() {
when:
loadConfig(CustomFilterPositionAtConfig)
then:
filterChain().filters.collect { it.class } == [OtherCustomFilter]
}
@Configuration
static class CustomFilterPositionAtConfig extends BaseWebConfig {
CustomFilterPositionAtConfig() {
// do not add the default filters to make testing easier
super(true)
}
protected void configure(HttpSecurity http) {
http
.addFilterAt(new OtherCustomFilter(), UsernamePasswordAuthenticationFilter.class)
}
}
def "http/custom-filter no AuthenticationManager in HttpSecurity"() {
@ -159,6 +180,13 @@ public class NamespaceHttpCustomFilterTests extends BaseSpringSpec {
}
static class CustomFilter extends UsernamePasswordAuthenticationFilter {}
static class OtherCustomFilter extends OncePerRequestFilter {
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(request,response);
}
}
static class CustomAuthenticationManager implements AuthenticationManager {
public Authentication authenticate(Authentication authentication)