配置 Spring Security 5 Oauth 2 以使用 access_token uri 参数
Posted
技术标签:
【中文标题】配置 Spring Security 5 Oauth 2 以使用 access_token uri 参数【英文标题】:Configure Spring Security 5 Oauth 2 to use access_token uri parameter 【发布时间】:2019-03-02 21:58:24 【问题描述】:我正在根据这个例子创建一个应用程序-
背景 -
https://github.com/spring-projects/spring-security/tree/master/samples/boot/oauth2resourceserver-webflux
OAuth2 令牌在 Header 中可以正常工作。
问题 -
但是,我想将其更改为在 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。
【问题讨论】:
【参考方案1】:你可以查看Spring Security的官方文档
您可以创建new ServerBearerTokenAuthenticationConverter()
,在ServerHttpSecurity
中设置allowUriQueryParameter
一个寄存器。
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)
http
// ...
.oauth2Login()
.authenticationConverter(converter) // set
.authenticationManager(manager)
.authorizedClientRepository(authorizedClients)
.clientRegistrationRepository(clientRegistrations);
return http.build();
【讨论】:
我正在尝试创建资源服务器。不幸的是,OAuth2ResourceServerSpec 不允许设置 authenticationConverter。 你不能,基本上。唯一的方法(至少从 Spring 5 和 WebFlux 5.1.3 开始)是编写一个 WebFilter 并将查询参数转换为标题。【参考方案2】:作为一种解决方法,您可以编写一个 WebFilter 来将 Query Parameter 转换为 Header。
【讨论】:
这没有提供问题的答案。一旦您有足够的声誉,您就可以对任何帖子发表评论;而是提供答案【参考方案3】:Spring MVC 有很多 WebFlux 所缺乏的合理默认值。这是其中之一。
我通过设置一个 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();
【讨论】:
【参考方案4】:现在有了 Spring Security 5.1.5,我们可以做到这一点 -
ServerBearerTokenAuthenticationConverter
authenticationConverter = new ServerBearerTokenAuthenticationConverter();
authenticationConverter.setAllowUriQueryParameter(true);
http.oauth2ResourceServer().bearerTokenConverter(authenticationConverter).jwt();
【讨论】:
我正在使用 Spring Security 5.3.3,并且这个 sn-p 的最后一行在 oauth2ResourceServer 中为 bearerTokenConverter 显示红色,因为它没有这样的成员。你知道我能做什么吗?谢谢。【参考方案5】:Pushkar 的答案对我不起作用,但帮助我找到了解决方案,以下代码起到了作用:
DefaultBearerTokenResolver resolver = new DefaultBearerTokenResolver();
resolver.setAllowUriQueryParameter(true);
http.authorizeRequests()
.anyRequest().authenticated()
.and().oauth2ResourceServer().bearerTokenResolver(resolver)
.jwt();
谢谢。
【讨论】:
在今天的Spring当前版本中,这绝对是正确的答案。DefaultBearerTokenResolver
与 ServerBearerTokenAuthenticationConverter
共享大量代码,似乎是现代的替代品。以上是关于配置 Spring Security 5 Oauth 2 以使用 access_token uri 参数的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security - 用于多租户应用程序的 OAuth、LDAP 集成
OpenID Connect 的 Spring Security 5 XML 配置
Spring Security(十五):5.6 Authentication
配置 Spring Security 5 Oauth 2 以使用 access_token uri 参数
在没有 servlet api 的 webflux 项目中使用 OAuth2 和 Spring Security OAuth2 和 reactor netty