PreAuthenticatedProcessingFilter位置

时间:2016-01-07 11:54:03

标签: java spring spring-mvc spring-security

查看the Spring documentation for pre-authentication scenarios,使用XML配置时,AbstractPreAuthenticatedProcessingFilter的实现似乎有一个特定的位置,即

<security:http>
<!-- Additional http configuration omitted -->
<security:custom-filter position="PRE_AUTH_FILTER" ref="refToMyPreAuthFilter" />
</security:http>

如何使用程序化配置实现相同的效果?据推测,应该在ExceptionTranslationFilter之前调用用于处理预身份验证的过滤器?但是,使用像

这样的东西
@Configuration
@EnableWebSecurity
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
          .addFilterBefore(new MyPreAuthFilter(), ExceptionTranslationFilter.class) 
        // ... additional configuration omitted
    }
}

似乎确实导致过滤器根本没被调用?仅使用

http.addFilter(new MyPreAuthFilter())

似乎有效,但我不确定过滤器是否添加到正确的位置(假设XML示例配置使用此过滤器的特定位置)?

使用

查看Filter Ordering in the Spring documentation
http.addFilterBefore(new MyPreAuthFilter(), ConcurrentSessionFilter.class) 

似乎是一个好地方,它可以在测试中使用。

任何人都可以确认这是这种过滤器的正确位置(或者,否则,确定正确的位置)?

1 个答案:

答案 0 :(得分:4)

在浏览了一下后,我发现了以下答案,我希望它对某些人有用。

TL; DR 仅使用http.addFilter(new MyPreAuthFilter)是正确的,因为AbstractPreAuthenticatedProcessingFilter的子类的正确顺序是自动建立的。

所以,这里是完整的解释:查看addFilter()HttpSecurity,我们看到它执行以下操作

public HttpSecurity addFilter(Filter filter) {
        Class<? extends Filter> filterClass = filter.getClass();
        if (!comparitor.isRegistered(filterClass)) {
            throw new IllegalArgumentException(...); // Complain about missing order
        }
        this.filters.add(filter);
        return this;
    }

首先,请注意以下两个事实:

  1. HttpSecurity::addFilterBeforeHttpSecurity::addFilterAfter实际上在首次注册给定的过滤器类HttpSecurity::addFilter后调用comparitor,例如

    public HttpSecurity addFilterAfter(Filter filter, 
            Class<? extends Filter> afterFilter) {
        comparitor.registerAfter(filter.getClass(), afterFilter);
        return addFilter(filter);
    }
    
  2. FilterComparitor::isRegistered不仅会检查给定的类,还会检查超类。

  3. 现在,请记住http.addFilter(new MyPreAuthFilter())其中(class MyPreAuthFilter extends AbstractPreAuthenticatedProcessingFilter { ... })工作时没有抛出异常。这意味着,AbstractPreAuthenticatedProcessingFilter(或其中一个超类)必须已在comparitor中注册。事实上,看constructor of FilterComparator我们看到以下顺序正在建立:

    ...
    final int STEP = 100;
    ...
    int order = 100;
    put(ChannelProcessingFilter.class, order);
    order += STEP;
    put(ConcurrentSessionFilter.class, order);
    order += STEP;
    ... // more filters
    put(X509AuthenticationFilter.class, order);
    order += STEP;
    put(AbstractPreAuthenticatedProcessingFilter.class, order);
    order += STEP;
    ...
    put(UsernamePasswordAuthenticationFilter.class, order);
            order += STEP;
    ...
    put(ExceptionTranslationFilter.class, order);
    order += STEP;
    put(FilterSecurityInterceptor.class, order);
    ...
    

    因此,对HttpSecurity::addFilter的子类使用AbstractPreAuthenticatedProcessingFilter是正确的答案。