How Does Spring Security Manage Built‑In Filter Order? A Deep Dive

This article explains how Spring Security’s HttpSecurity class maintains the order of its built‑in filters using FilterOrderRegistration, demonstrates the registration and retrieval logic with code examples, and clarifies how duplicate orders are resolved during filter sorting.

Programmer DD
Programmer DD
Programmer DD
How Does Spring Security Manage Built‑In Filter Order? A Deep Dive

Spring Security’s HttpSecurity contains a member variable FilterOrderRegistration, which acts as a registry for built‑in filters. The registry holds a map filterToOrder that records each filter’s order and the step size between them.

Built‑in Filter Order

The following code copies the registration map and prints the filters in order:

CopyFilterOrderRegistration filterOrderRegistration = new CopyFilterOrderRegistration();
// Get built‑in filters (method not provided)
Map<String, Integer> filterToOrder = filterOrderRegistration.getFilterToOrder();
TreeMap<Integer, String> orderToFilter = new TreeMap<>();
filterToOrder.forEach((name, order) -> orderToFilter.put(order, name));
orderToFilter.forEach((order, name) -> System.out.println(" 顺序:" + order + " 类名:" + name));

The printed result shows that the relative positions of built‑in filters are fixed: the first step is 200, while all subsequent steps are 100.

Built‑in filters are only pre‑positioned; they become effective only when HttpSecurity explicitly adds them via the addFilterXXXX series of methods.

Registration Logic

FilterOrderRegistration

provides a put method to register a filter with a specific position:

void put(Class<? extends Filter> filter, int position) {
    String className = filter.getName();
    // Ignore if already registered
    if (this.filterToOrder.containsKey(className)) {
        return;
    }
    // Register the order
    this.filterToOrder.put(className, position);
}

From this we can conclude:

The 34 built‑in filters have immutable order numbers.

New filters must have fully qualified class names that do not duplicate built‑in ones.

New filters may share the same order number as built‑in filters.

Retrieving a Filter’s Order

FilterOrderRegistration

also offers a getOrder method that walks up the class hierarchy to find an order value:

Integer getOrder(Class<?> clazz) {
    while (clazz != null) {
        Integer result = this.filterToOrder.get(clazz.getName());
        if (result != null) {
            return result;
        }
        clazz = clazz.getSuperclass();
    }
    return null;
}

HttpSecurity’s Filter Management Methods

The private method addFilterAtOffsetOf calculates a new filter’s order based on a registered filter and an offset, then adds it to the internal list:

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));
    this.filterOrders.put(filter.getClass(), order);
    return this;
}
Remember that registeredFilter must already be present in FilterOrderRegistration .

Other convenience methods delegate to this logic. For example, addFilterAfter simply calls addFilterAtOffsetOf(filter, 1, afterFilter), placing the new filter one position after the specified one.

public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) {
    return addFilterAtOffsetOf(filter, 1, afterFilter);
}

The generic addFilter method requires the filter to already have a registered order; otherwise it throws an exception, encouraging the use of addFilterBefore or addFilterAfter instead.

public HttpSecurity addFilter(Filter filter) {
    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(new OrderedFilter(filter, order));
    return this;
}

What Happens with Duplicate Orders?

If two filters are registered with the same order number, Spring Security sorts them by the natural order of the numbers; when numbers are equal, the filter added earlier (lower index) appears first.

// filters list
private List<OrderedFilter> filters = new ArrayList<>();
// sort
this.filters.sort(OrderComparator.INSTANCE);

The OrderComparator performs a numeric comparison, and for equal numbers it preserves insertion order, so the first added filter takes precedence.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavaSecurity Filtersspring-securityFilter OrderHttpSecurity
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.