Как проверить несколько токенов на предъявителя с помощью Spring SecurityJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как проверить несколько токенов на предъявителя с помощью Spring Security

Сообщение Anonymous »

Я работаю над веб-приложением Spring Boot (3.5.x), используя Spring Security и сервер ресурсов OAuth2. Мне нужно поддерживать два типа токенов носителя для аутентификации:
  • Стандартный JWT носителя: отправляется в заголовке Authorization (например, Authorization: Bearer ) с областями/полномочиями.
  • JWT пользовательского сеанса: отправляется в настраиваемом заголовке (например, X-Authorization-Session: Bearer ), который не содержит никаких полномочий — его нужно просто проверить на подлинность (срок действия, эмитент, подпись и т. д.).
Мои требования:
  • Некоторым конечным точкам должен требоваться только токен сеанса (просто проверьте достоверность, без полномочий).
  • Некоторым конечным точкам требуется и то, и другое: сначала проверка токена сеанса, затем проверка стандартного токена носителя и использование его полномочий для авторизации.
  • Некоторым конечным точкам требуется только стандартный токен носителя.
Я уже реализовал AuthenticationManagerResolver /

Код: Выделить всё

ReactiveAuthenticationManagerResolver
, который может обрабатывать несколько эмитентов, и если я использую стандартную конфигурацию, например:

Код: Выделить всё

oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(standardBearerTokenAuthenticationManagerResolver))
...все работает нормально, если я настраиваю SecurityFilterChain / SecurityWebFilterChain только для авторизации конечных точек, используя только токен стандартного носителя, применяя @PreAuthorize или напрямую вызывая .hasRole() / .hasAuthority() в AuthorizeExchangeSpec:

Код: Выделить всё

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http, ReactiveAuthenticationManagerResolver authManagerResolver) {
Customizer authorizeExchangeCustomizer = authorizeExchangeSpec -> authorizeExchangeSpec
.pathMatchers("/api/public").permitAll()
.anyExchange().authenticated();
return http
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.authorizeExchange(authorizeExchangeCustomizer)
.oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authManagerResolver))
.build();
}
Я не могу понять, как настроить Spring Security, чтобы я мог смешивать/сопоставлять оба валидатора токенов на основе моих ранее упомянутых требований. До сих пор я пробовал использовать несколько bean-компонентов SecurityFilterChain с разными конфигурациями securityMatcher() иauthorizeHttpRequests(). Первая цепочка аннотируется @Order(1), а конфигурация oauth2 применяется с использованием конкретного ReactiveAuthenticationManagerResolver, а также ServerBearerTokenAuthenticationConverter с .setBearerTokenHeaderName("X-Authorization-Session"). Затем я настраиваю вторую цепочку безопасности с помощью @Order(2), которая устанавливает стандартный токен носителя, используя тот же .oauth2ResourceServer(oauth2 -> ...). Третья цепочка предназначена для настройки любых общедоступных конечных точек с помощью .permitall() и т. д. Проблема с этим подходом заключается в том, что если есть конечные точки, где должны использоваться оба этих токена, сначала запускается SecurityFilterChain с @Order(1), настроенный для токена носителя сеанса, успешно аутентифицирует запрос, и, поскольку токен сеанса не содержит никаких полномочий, запрос запрещается. Пример:

Код: Выделить всё

@Bean
@Order(1)
public SecurityWebFilterChain sessionTokenSecurityWebFilterChain(ServerHttpSecurity http, ReactiveAuthenticationManagerResolver sessionAuthResolver) {
ServerWebExchangeMatcher sessionTokenPaths = ServerWebExchangeMatchers.pathMatchers("/api/session", "/api/sessionAndStandardToken");
var sessionTokenConverter = new ServerBearerTokenAuthenticationConverter();
sessionTokenConverter.setBearerTokenHeaderName("X-Authorization-Session");
return http
.securityMatcher(sessionTokenPaths)
.authorizeExchange(exchange -> exchange.matchers(sessiontokenPaths).authenticated())
.oauth2ResourceServer(oAuth2 -> oAuth2.authenticationManagerResolver(sessionAuthResolver)
.bearerTokenConverter(sessionTokenConverter))
.build();
}

@Bean
@Order(2)
public SecurityWebFilterChain standardTokenSecurityWebFilterChain(ServerHttpSecurity http,ReactiveAuthenticationManagerResolver standardAuthResolver) {
ServerWebExchangeMatcher standardTokenPaths = ServerWebExchangeMatchers.pathMatchers("/api/admin",  "/api/sessionAndStandardToken");
return http
.securityMatcher(standardTokenPaths)
.authorizeExchange(exchange -> exchange.matchers(standardTokenPaths).authenticated())
.oauth2ResourceServer(oAuth2 -> oAuth2.authenticationManagerResolver(standardAuthResolver))
.build();
}

@Bean
@Order(3)
public SecurityWebFilterChain defaultSecurityWebFilterChain(ServerHttpSecurity http) {
return http
.securityMatcher(ServerWebExchangeMatchers.anyExchange())
.authorizeExchange(exchange -> exchange.pathMatchers("/api.public").permitAll())
.build();
}
Как настроить Spring Security для поддержки этих сценариев и гарантировать, что для конечных точек, требующих обоих токенов, сначала проверяется токен сеанса, и только если он действителен, стандартный токен носителя проверяется на предмет полномочий? Есть ли рекомендуемый способ структурировать эту логику в Spring Security 6+?


Подробнее здесь: https://stackoverflow.com/questions/798 ... g-security
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»