我们正在将一个使用带有xml配置的spring security 3.2的大型项目迁移到具有spring-security 5.0和编程配置的当前spring boot堆栈中。 通过在过滤器链的末尾将注销成功处理程序注册为自定义过滤器,可以很好地完成旧的注销操作。 旧的xml配置的相关部分:
[...]
<http pattern="/oauth/(users|clients)/.*" request-matcher="regex" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" use-expressions="true" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/oauth/users/revoke" method="POST" access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient())" />
<intercept-url pattern="/**" access="denyAll()" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<expression-handler ref="oauthWebExpressionHandler" />
<custom-filter ref="revokeFilter" before="LAST" />
</http>
[...]
<bean id="revokeFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg>
<bean class="com.company.management.authorization.oauth2.RevokeSuccessHandler" />
</constructor-arg>
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/oauth/users/revoke" />
</bean>
[...]
这导致了以下过滤器链:
Security filter chain: [
SecurityContextPersistenceFilter
WebAsyncManagerIntegrationFilter
OAuth2AuthenticationProcessingFilter
SecurityContextHolderAwareRequestFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
LogoutFilter
]
当我现在通过以下方式添加注销成功处理程序来配置资源服务器时:
@Override
public void configure( HttpSecurity http ) throws Exception
{
http.regexMatcher( "/oauth/(users|clients)/.*" )
.anonymous( ).disable( ).authorizeRequests( )
.regexMatchers( HttpMethod.POST, "/oauth/users/revoke" )
.access( "#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient())" )
.antMatchers( "/**" ).denyAll( )
.and( ).sessionManagement( ).sessionCreationPolicy( SessionCreationPolicy.STATELESS )
.and( ).csrf( ).disable( ).exceptionHandling( )
.accessDeniedHandler( this.oAuth2AccessDeniedHandler )
.defaultAuthenticationEntryPointFor( this.oauthAuthenticationEntryPoint,new AntPathRequestMatcher( "/**" ) )
.and( ).logout( ).logoutUrl( "/oauth/users/revoke" ).logoutSuccessHandler( revokeSuccessHandler( ) );
}
在应用OAuth2AuthenticationProcessingFilter之前,将触发注销处理程序,因此未进行任何身份验证。过滤器链如下所示:
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
OAuth2AuthenticationProcessingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
注销成功处理程序中的身份验证对象为null,并且处理程序中的逻辑(基于给定的身份验证对象进行了一些其他检查)不再起作用。 如果我删除注销成功处理程序,则OAuth2AuthenticationProcessingFilter检查将正确完成,并且身份验证将按预期进行(但是,当然会丢失注销)。 如果我更改注销处理程序中的逻辑并从请求的Authorization标头中剥离令牌,则可以从令牌存储加载授权,然后再次手动实施访问检查,但这似乎不是这种方式应该做的...
所以,主要的问题是,LogoutFilter是在过滤器链中的OAuth2AuthenticationProcessingFilter之前设置的,我找不到改变顺序的方法。
我试图将属性security.oauth2.resource.filter-order
设置为3,但这没有帮助。我还为@Order
注释尝试了其他值,但是没有运气。
我想办法可能是通过执行类似{{1}
但是我无法实例化必要的LogoutFilter类,因为它需要LogoutHandlers列表作为构造函数参数,而我没有(传递null会导致错误,并且尝试自动装配也行不通)。
那么,实现正确的过滤器顺序的正确方法是什么?