Spring Security OAuth2: выражения «# oauth2.xxx» не оцениваются с помощью нескольких RequestMatchers, сопоставленных с одним и тем же FilterChain - PullRequest
0 голосов
/ 04 января 2019

В многомодульном приложении я определил 5 RequestMatchers, сопоставленных с той же FilterChain, как показано ниже:

@Configuration
public class Module1SecurityFilterChain extends ResourceServerConfigurerAdapter {

   @Override
   public void configure( HttpSecurity http ) throws Exception {
      http.sessionManagement().sessionCreationPolicy( STATELESS );
      http.requestMatchers().antMatchers( "/module1/**")
            .and()
            .authorizeRequests()
            .antMatchers( "/module1/resource").authenticated()
            .antMatchers( "/module1/test" ).access( "#oauth2.isClient()")
            .anyRequest().access( "#oauth2.hasScope('webclient')" );
   }
}

И module2:

@Configuration
public class Module2SecurityFilterChain extends ResourceServerConfigurerAdapter {

   @Override
   public void configure( HttpSecurity http ) throws Exception {
      http.sessionManagement().sessionCreationPolicy( STATELESS );
      http.requestMatchers().antMatchers( "/module2/**")
            .and()
            .authorizeRequests()
            .antMatchers( "/module2/resource").authenticated()
            .antMatchers( "/module2/test" ).access( "#oauth2.isClient()")
            .anyRequest().access( "#oauth2.hasScope('webclient')" );
   }
}

И включенный метод безопасности:

@Configuration
@EnableGlobalMethodSecurity( prePostEnabled = true, securedEnabled = true )
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}

Проблема в том, что все выражения #oauth2.xx вычисляются только для 1-го модуля requestmatcher /module1/** и игнорируются в других.Когда я аутентифицирую пользователя и пытаюсь получить доступ к /module1/test, доступ запрещается, как и ожидалось, тогда как при доступе к /module2/test доступ разрешается (также следует запретить).

Может кто-нибудь объяснить мне, почему и как это решить?Я знаю, что Spring Security совсем непросто ... Еще раз спасибо.

РЕДАКТИРОВАТЬ @Darren Forsythe (спасибо за ваш комментарий) Созданы цепочки фильтров:

INFO | o.s.s.w.DefaultSecurityFilterChain | Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/oauth/token'], Ant [pattern='/oauth/token_key'], Ant [pattern='/oauth/check_token']]], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@f55a810b, org.springframework.security.web.context.SecurityContextPersistenceFilter@85021903, org.springframework.security.web.header.HeaderWriterFilter@1d0744d1, org.springframework.security.web.authentication.logout.LogoutFilter@2d15146a, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@c38f3266, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@8f9bf85, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@74a71be5, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@e4eb6cc, org.springframework.security.web.session.SessionManagementFilter@22f6b39a, org.springframework.security.web.access.ExceptionTranslationFilter@960c464f, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@f7a19dc5]
INFO | o.s.s.w.DefaultSecurityFilterChain | Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/module1/**'], Ant [pattern='/module2/**'], Ant [pattern='/module3/**'], Ant [pattern='/module4/**'], Ant [pattern='/module5/**'], Ant [pattern='/module6/**']]], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@38ef2427, org.springframework.security.web.context.SecurityContextPersistenceFilter@a26ff7af, org.springframework.security.web.header.HeaderWriterFilter@5344e710, org.springframework.security.web.authentication.logout.LogoutFilter@da0534c8, org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter@2956c7ab, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5682f610, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@f4cbf7a4, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@d1b1395a, org.springframework.security.web.session.SessionManagementFilter@d352f8ab, org.springframework.security.web.access.ExceptionTranslationFilter@9bb1d86, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@73c7a695]
INFO | o.s.s.w.DefaultSecurityFilterChain | Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1cc2056f, org.springframework.security.web.context.SecurityContextPersistenceFilter@259d95db, org.springframework.security.web.header.HeaderWriterFilter@de089e0b, org.springframework.security.web.authentication.logout.LogoutFilter@8b86b4c, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@96304ca8, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1d5b7e4b, org.springframework.security.web.session.SessionManagementFilter@bd586b4d, org.springframework.security.web.access.ExceptionTranslationFilter@7cff2571]

Как видите, все URL-адреса модулей отображаются в одной и той же цепочке фильтров с этим списком фильтров:

Security filter chain: [
  WebAsyncManagerIntegrationFilter
  SecurityContextPersistenceFilter
  HeaderWriterFilter
  LogoutFilter
  OAuth2AuthenticationProcessingFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]

Я не понимаю, почему для других модулей выражение #oauth2.xxне оценивается, так как FilterChain - это то же самое?

1 Ответ

0 голосов
/ 08 января 2019

Соответствующие запросы (указанные в antMatchers, anyRequest и т. Д.) Обрабатываются цепочкой фильтров в указанном порядке.Поскольку несколько ResourceServiceConfiguredAdapter экземпляров просто настраиваются на один и тот же экземпляр HttpSecurity, для каждого из ваших запросов сопоставления обрабатываются примерно так:

if (uri == "/module1/resource") {
    // ...
} else if (uri == "/module1/test") { 
    // ...
} else if (true) { // anyRequest
    // ...
} else if (uri = "/module2/resource") {
    // ...
} else if (uri = "/module2/test") {
    // ...
}

Как видите, последние два, еслиусловия никогда не будут достигнуты.

Вот две вещи, которые вы можете рассмотреть:

Заменить anyRequest()

anyRequest обычно очень удобно;однако в данном случае вы на самом деле не имеете в виду «любой запрос», поскольку пытаетесь сузить область видимости до определенных путей модулей.Вместо этого вы могли бы сделать:

http
    .requestMatchers()
        .antMatchers("/module2/**")
        .and()
    .authorizeRequests()
        .antMatchers("/module2/resource").authenticated()
        .antMatchers("/module2/test").access( "#oauth2.isClient()")
        .antMatchers("/module2/**").access( "#oauth2.hasScope('webclient')" );

Таким образом, модуль не перегружен и не пытается указать поведение, о котором, возможно, он не знает.

По правде говоря, он обычно безвреден дляпозвоните anyRequest, так как вы уже сужаете область действия цепочки фильтров с помощью requestMatchers.Но поскольку вы создаете один HttpSecurity с несколькими адаптерами, это скрытая сложность.

oauth2ResourceServer() - Spring Security 5.1 +

Если вы используете Spring Security5.1 , то есть фактически поддержка, встроенная в WebSecurityConfigurerAdapter изначально, так что вам больше не нужно использовать ResourceServerConfigurerAdapter, по крайней мере для JWT-кодированных токенов на данный момент.Это также хорошо, потому что два WebSecurityConfigurerAdapter обрабатываются как отдельные цепочки фильтров.

В зависимости от необходимых вам функций OAuth 2.0 вы можете сделать это вместо этого:

@EnableWebSecurity
public class Module1Config extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .requestMatchers()
                .antMatchers("/module1/**")
                .and()
            .authorizeRequests()
                .antMatchers("/module1/resource").authenticated()
                .anyRequest.hasRole("SCOPE_webclient")
            .oauth2ResourceServer()
                .jwt();
    }
}

Сейчас это активная область разработки для Spring Security - перенос функций в WebSecurityConfigurerAdapter;так что определенно обращайтесь к вашему конкретному варианту использования, чтобы убедиться, что он имеет приоритет, если он еще не на месте.

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