从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)
似乎是一个好地方,它可以在测试中工作。
谁能确认这是此类过滤器的正确位置(否则,请命名正确的位置)?
最佳答案
浏览更多点之后,我发现了以下答案,希望它对某些人有用。
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;
}
首先,请注意以下两个事实:
HttpSecurity::addFilterBefore
和 HttpSecurity::addFilterAfter
实际上在首先注册给定的过滤器类HttpSecurity::addFilter
之后实际上调用comparitor
。public HttpSecurity addFilterAfter(Filter filter,
Class<? extends Filter> afterFilter) {
comparitor.registerAfter(filter.getClass(), afterFilter);
return addFilter(filter);
}
FilterComparitor::isRegistered
不仅检查给定的类,还检查超类。 现在,请记住
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
是正确的答案。