|  | @@ -16,14 +16,21 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  package org.springframework.security.config.annotation.web.builders;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +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;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  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;
 | 
	
	
		
			
				|  | @@ -127,11 +134,11 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	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
 | 
	
	
		
			
				|  | @@ -2522,8 +2529,12 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	@Override
 | 
	
		
			
				|  |  |  	protected DefaultSecurityFilterChain performBuild() {
 | 
	
		
			
				|  |  | -		this.filters.sort(this.comparator);
 | 
	
		
			
				|  |  | -		return new DefaultSecurityFilterChain(this.requestMatcher, this.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);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	@Override
 | 
	
	
		
			
				|  | @@ -2544,24 +2555,28 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	@Override
 | 
	
		
			
				|  |  |  	public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) {
 | 
	
		
			
				|  |  | -		this.comparator.registerAfter(filter.getClass(), afterFilter);
 | 
	
		
			
				|  |  | -		return addFilter(filter);
 | 
	
		
			
				|  |  | +		return addFilterAtOffsetOf(filter, 1, afterFilter);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	@Override
 | 
	
		
			
				|  |  |  	public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) {
 | 
	
		
			
				|  |  | -		this.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;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	@Override
 | 
	
		
			
				|  |  |  	public HttpSecurity addFilter(Filter filter) {
 | 
	
		
			
				|  |  | -		Class<? extends Filter> filterClass = filter.getClass();
 | 
	
		
			
				|  |  | -		if (!this.comparator.isRegistered(filterClass)) {
 | 
	
		
			
				|  |  | -			throw new IllegalArgumentException("The Filter class " + filterClass.getName()
 | 
	
		
			
				|  |  | +		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;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -2584,8 +2599,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
 | 
	
		
			
				|  |  |  	 * @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);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/**
 | 
	
	
		
			
				|  | @@ -2973,4 +2987,37 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/**
 | 
	
		
			
				|  |  | +	 * 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 + '}';
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }
 |