Spring security5: LogoutFilter запускается перед проверкой OAuth2 - PullRequest
0 голосов
/ 16 октября 2018

Мы переносим большой проект, использующий Spring Security 3.2 с конфигурацией XML, в текущий загрузочный стек Spring с Spring-Security 5.0 и программной конфигурацией.Старый выход работал хорошо, регистрируя обработчик выхода из системы в качестве пользовательского фильтра в конце цепочки фильтров.Соответствующая часть старой 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
]

Когда я сейчас настраиваю сервер ресурсов, добавив обработчик успеха выхода из системы, этоway:

@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
]

Объект аутентификации в обработчике успеха выхода из системы равен нулю, а логика в обработчике (с некоторыми дополнительными проверками на основе данного объекта аутентификации) больше не работает.Если я удаляю обработчик успеха выхода из системы, проверки OAuth2AuthenticationProcessingFilter выполняются правильно, и аутентификация работает как задумано (но тогда, конечно, выход из системы отсутствует).Если я изменю логику в обработчике выхода из системы и уберу токен из заголовка авторизации запроса, я мог бы загрузить авторизацию из хранилища токенов, а затем снова выполнить проверки доступа вручную, но, похоже, это не так.должно быть сделано ...

Итак, главная проблема в том, что LogoutFilter установлен перед OAuth2AuthenticationProcessingFilter в цепочке фильтров, и я не смог найти способ изменить порядок.Я попытался установить для свойства security.oauth2.resource.filter-order значение 3, но это не помогло.Я также пробовал разные значения для аннотации @Order, но безуспешно.Я полагаю, что можно пойти путем добавления пользовательского фильтра типа LogoutFilter после OAuth2AuthenticationProcessingFilter (или «до последнего», как это было сделано в конфигурации xml), выполнив что-то вроде and( ).addFilterAfter( revokeFilterBean(), OAuth2AuthenticationProcessingFilter.class ) Но я не могу создать экземпляр необходимогоКласс LogoutFilter, так как ему нужен список LogoutHandlers в качестве аргумента конструктора, которого у меня нет (передача нулевого значения приводит к ошибке и попытка автопроводки тоже не сработает).

Итак, как правильно?добиться правильного порядка фильтра?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...