将Spring Security 5 Oauth 2配置为使用access_token uri参数

时间:2018-09-27 04:08:19

标签: spring spring-boot spring-security spring-security-oauth2 spring-webflux

我正在基于此示例创建应用程序-

背景-

https://github.com/spring-projects/spring-security/tree/master/samples/boot/oauth2resourceserver-webflux

它的工作原理非常好,因为OAuth2令牌位于标头中。

问题-

但是我想更改它以在URL中使用OAuth 2令牌。我正在尝试创建OAuth2资源服务器。

分析-

Spring Security似乎支持从access_token参数获取令牌-

https://github.com/spring-projects/spring-security/blob/e3eaa99ad06769cf44ad3e1249f6398077b90834/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java#L57

但是默认情况下似乎已禁用-

https://github.com/spring-projects/spring-security/blob/master/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/server/ServerBearerTokenAuthenticationConverter.java#L48

现在无法在Spring层次结构之外直接访问该类-

https://github.com/spring-projects/spring-security/blob/master/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java#L955

问题?

是否可以在我的代码中将此 allowUriQueryParameter 设置为true?

更新

我正在创建OAuth2资源服务器。不幸的是,OAuth2ResourceServerSpec不允许设置authenticationConverter。

5 个答案:

答案 0 :(得分:2)

您可以查看Spring Security的官方文档

您可以创建gestureRecognizer.horizontalDirection(target: self) ,在new ServerBearerTokenAuthenticationConverter()中为allowUriQueryParameter设置寄存器。

ServerHttpSecurity

答案 1 :(得分:1)

Spring MVC具有WebFlux中缺少的许多合理的默认值。这就是其中之一。

我通过设置一个WebFilter来解决此问题,该WebFilter在查询字符串中使用令牌并将其添加到标题中。

@Override
@NonNull
public Mono<Void> filter(
  @NonNull ServerWebExchange serverWebExchange, @NonNull WebFilterChain 
     webFilterChain) {
  ServerHttpRequest request = serverWebExchange.getRequest();
  return webFilterChain.filter(
    serverWebExchange.mutate().request(sanitizeRequest(request)).build());
}

private ServerHttpRequest sanitizeRequest(ServerHttpRequest request) {
  MultiValueMap<String, String> queryParams = request.getQueryParams();
  ServerHttpRequest.Builder newRequest =
    request
        .mutate()
        .headers(
            headers -> {
              if (headerContainsAuthorizationKey(headers)) {
                String token = getAuthorizationBearer(headers);
                if (token != null) {
                  // "bearer" breaks WebFlux OAuth :)
                  headers.set(HttpHeaders.AUTHORIZATION, token.replace("bearer", "Bearer"));
                  return;
                }
              }
              if (pathContainsAccessToken(queryParams)) {
                headers.set(
                    HttpHeaders.AUTHORIZATION,
                    "Bearer " + queryParams.getFirst("access_token"));
              }
            });

  if (pathContainsAccessToken(queryParams)) {
    newRequest.uri(buildNewUriWithoutToken(request.getURI(), queryParams));
  }
  return newRequest.build();
 }
}

很高兴指出,小写的“ bearer”也破坏了WebFlux。

之后,您可以在安全链中的oauthResourceServer规范之前添加此过滤器:

@Bean
public SecurityWebFilterChain springSecurityFilterChain(
  ServerHttpSecurity http,
  TokenStore tokenStore,
  AuthorizationHeaderFilter authorizationHeaderFilter) {
    http.csrf()
      .disable()
      .authorizeExchange()
      .anyExchange()
      .authenticated()
      .and()
      .addFilterAt(authorizationHeaderFilter, SecurityWebFiltersOrder.FIRST)
      .oauth2ResourceServer()
      .jwt() // ...  etc
  return http.build();
}

答案 2 :(得分:1)

Pushkar 的答案对我不起作用,但帮助我找到了解决方案,以下代码可以解决问题:

DefaultBearerTokenResolver resolver = new DefaultBearerTokenResolver();
resolver.setAllowUriQueryParameter(true);

http.authorizeRequests()
        .anyRequest().authenticated()
        .and().oauth2ResourceServer().bearerTokenResolver(resolver)
        .jwt();

谢谢。

答案 3 :(得分:0)

作为一种解决方法,您可以编写一个WebFilter将查询参数转换为标题。

答案 4 :(得分:0)

现在有了Spring Security 5.1.5,我们可以做到这一点-

ServerBearerTokenAuthenticationConverter 
authenticationConverter = new ServerBearerTokenAuthenticationConverter();
authenticationConverter.setAllowUriQueryParameter(true);

http.oauth2ResourceServer().bearerTokenConverter(authenticationConverter).jwt();