|
@@ -16,6 +16,8 @@
|
|
|
package org.springframework.security.config.annotation.web.builders;
|
|
|
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
+import org.springframework.core.OrderComparator;
|
|
|
+import org.springframework.core.Ordered;
|
|
|
import org.springframework.http.HttpMethod;
|
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
|
import org.springframework.security.authentication.AuthenticationProvider;
|
|
@@ -78,10 +80,16 @@ import org.springframework.web.cors.CorsConfiguration;
|
|
|
import org.springframework.web.filter.CorsFilter;
|
|
|
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+
|
|
|
import javax.servlet.Filter;
|
|
|
+import javax.servlet.FilterChain;
|
|
|
+import javax.servlet.ServletException;
|
|
|
+import javax.servlet.ServletRequest;
|
|
|
+import javax.servlet.ServletResponse;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
|
/**
|
|
@@ -125,9 +133,9 @@ public final class HttpSecurity extends
|
|
|
implements SecurityBuilder<DefaultSecurityFilterChain>,
|
|
|
HttpSecurityBuilder<HttpSecurity> {
|
|
|
private final RequestMatcherConfigurer requestMatcherConfigurer;
|
|
|
- private List<Filter> filters = new ArrayList<>();
|
|
|
+ private List<OrderedFilter> filters = new ArrayList<>();
|
|
|
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
|
|
|
- private FilterComparator comparator = new FilterComparator();
|
|
|
+ private FilterOrderRegistration filterOrders = new FilterOrderRegistration();
|
|
|
|
|
|
/**
|
|
|
* Creates a new instance
|
|
@@ -2528,8 +2536,12 @@ public final class HttpSecurity extends
|
|
|
|
|
|
@Override
|
|
|
protected DefaultSecurityFilterChain performBuild() {
|
|
|
- filters.sort(comparator);
|
|
|
- return new DefaultSecurityFilterChain(requestMatcher, filters);
|
|
|
+ this.filters.sort(OrderComparator.INSTANCE);
|
|
|
+ List<Filter> sortedFilters = new ArrayList<>(this.filters.size());
|
|
|
+ for (Filter filter : this.filters) {
|
|
|
+ sortedFilters.add(((OrderedFilter) filter).filter);
|
|
|
+ }
|
|
|
+ return new DefaultSecurityFilterChain(this.requestMatcher, sortedFilters);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2570,8 +2582,7 @@ public final class HttpSecurity extends
|
|
|
* .servlet.Filter, java.lang.Class)
|
|
|
*/
|
|
|
public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) {
|
|
|
- comparator.registerAfter(filter.getClass(), afterFilter);
|
|
|
- return addFilter(filter);
|
|
|
+ return addFilterAtOffsetOf(filter, 1, afterFilter);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2583,8 +2594,13 @@ public final class HttpSecurity extends
|
|
|
*/
|
|
|
public HttpSecurity addFilterBefore(Filter filter,
|
|
|
Class<? extends Filter> beforeFilter) {
|
|
|
- comparator.registerBefore(filter.getClass(), beforeFilter);
|
|
|
- return addFilter(filter);
|
|
|
+ return addFilterAtOffsetOf(filter, -1, beforeFilter);
|
|
|
+ }
|
|
|
+
|
|
|
+ private HttpSecurity addFilterAtOffsetOf(Filter filter, int offset, Class<? extends Filter> registeredFilter) {
|
|
|
+ int order = this.filterOrders.getOrder(registeredFilter) + offset;
|
|
|
+ this.filters.add(new OrderedFilter(filter, order));
|
|
|
+ return this;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2595,14 +2611,12 @@ public final class HttpSecurity extends
|
|
|
* servlet.Filter)
|
|
|
*/
|
|
|
public HttpSecurity addFilter(Filter filter) {
|
|
|
- Class<? extends Filter> filterClass = filter.getClass();
|
|
|
- if (!comparator.isRegistered(filterClass)) {
|
|
|
- throw new IllegalArgumentException(
|
|
|
- "The Filter class "
|
|
|
- + filterClass.getName()
|
|
|
- + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
|
|
|
+ Integer order = this.filterOrders.getOrder(filter.getClass());
|
|
|
+ if (order == null) {
|
|
|
+ throw new IllegalArgumentException("The Filter class " + filter.getClass().getName()
|
|
|
+ + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
|
|
|
}
|
|
|
- this.filters.add(filter);
|
|
|
+ this.filters.add(new OrderedFilter(filter, order));
|
|
|
return this;
|
|
|
}
|
|
|
|
|
@@ -2626,8 +2640,7 @@ public final class HttpSecurity extends
|
|
|
* @return the {@link HttpSecurity} for further customizations
|
|
|
*/
|
|
|
public HttpSecurity addFilterAt(Filter filter, Class<? extends Filter> atFilter) {
|
|
|
- this.comparator.registerAt(filter.getClass(), atFilter);
|
|
|
- return addFilter(filter);
|
|
|
+ return addFilterAtOffsetOf(filter, 0, atFilter);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -3023,4 +3036,38 @@ public final class HttpSecurity extends
|
|
|
}
|
|
|
return apply(configurer);
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * A Filter that implements Ordered to be sorted. After sorting occurs, the original
|
|
|
+ * filter is what is used by FilterChainProxy
|
|
|
+ */
|
|
|
+ private static final class OrderedFilter implements Ordered, Filter {
|
|
|
+
|
|
|
+ private final Filter filter;
|
|
|
+
|
|
|
+ private final int order;
|
|
|
+
|
|
|
+ private OrderedFilter(Filter filter, int order) {
|
|
|
+ this.filter = filter;
|
|
|
+ this.order = order;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
|
|
+ throws IOException, ServletException {
|
|
|
+ this.filter.doFilter(servletRequest, servletResponse, filterChain);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int getOrder() {
|
|
|
+ return this.order;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String toString() {
|
|
|
+ return "OrderedFilter{" + "filter=" + this.filter + ", order=" + this.order + '}';
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|