配置 Spring Security 5 Oauth 2 以使用 access_token uri 参数
Configure Spring Security 5 Oauth 2 to use access_token uri parameter
我正在基于此示例创建应用程序 -
背景 -
OAuth2 令牌在 Header 中,它工作得很好。
问题-
但是我想将其更改为在 url 中使用 OAuth 2 令牌。我正在尝试创建一个 OAuth2 资源服务器。
分析-
似乎Spring安全支持从access_token参数获取令牌-
不过好像默认是禁用的-
现在这个class在spring层级之外是不可访问的直接在这里创建-
有问题吗?
是否可以在我的代码中将此 allowUriQueryParameter 设置为 true?
更新
我正在创建一个 OAuth2 资源服务器。不幸的是,OAuth2ResourceServerSpec 不允许设置 authenticationConverter。
你可以查看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();
}
作为解决方法,您可以编写 WebFilter 将查询参数转换为 Header。
Spring MVC 有很多 WebFlux 所缺少的合理默认值。这是其中之一。
我通过设置一个 WebFilter 来解决这个问题,该 WebFilter 在查询字符串中获取标记并将它们添加到 header。
@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();
}
现在使用 Spring Security 5.1.5 我们可以做到这一点 -
ServerBearerTokenAuthenticationConverter
authenticationConverter = new ServerBearerTokenAuthenticationConverter();
authenticationConverter.setAllowUriQueryParameter(true);
http.oauth2ResourceServer().bearerTokenConverter(authenticationConverter).jwt();
Pushkar 的答案对我不起作用,但帮助我找到了解决方案,以下代码可以解决问题:
DefaultBearerTokenResolver resolver = new DefaultBearerTokenResolver();
resolver.setAllowUriQueryParameter(true);
http.authorizeRequests()
.anyRequest().authenticated()
.and().oauth2ResourceServer().bearerTokenResolver(resolver)
.jwt();
谢谢。
我正在基于此示例创建应用程序 -
背景 -
OAuth2 令牌在 Header 中,它工作得很好。
问题-
但是我想将其更改为在 url 中使用 OAuth 2 令牌。我正在尝试创建一个 OAuth2 资源服务器。
分析-
似乎Spring安全支持从access_token参数获取令牌-
不过好像默认是禁用的-
现在这个class在spring层级之外是不可访问的直接在这里创建-
有问题吗?
是否可以在我的代码中将此 allowUriQueryParameter 设置为 true?
更新
我正在创建一个 OAuth2 资源服务器。不幸的是,OAuth2ResourceServerSpec 不允许设置 authenticationConverter。
你可以查看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();
}
作为解决方法,您可以编写 WebFilter 将查询参数转换为 Header。
Spring MVC 有很多 WebFlux 所缺少的合理默认值。这是其中之一。
我通过设置一个 WebFilter 来解决这个问题,该 WebFilter 在查询字符串中获取标记并将它们添加到 header。
@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();
}
现在使用 Spring Security 5.1.5 我们可以做到这一点 -
ServerBearerTokenAuthenticationConverter
authenticationConverter = new ServerBearerTokenAuthenticationConverter();
authenticationConverter.setAllowUriQueryParameter(true);
http.oauth2ResourceServer().bearerTokenConverter(authenticationConverter).jwt();
Pushkar 的答案对我不起作用,但帮助我找到了解决方案,以下代码可以解决问题:
DefaultBearerTokenResolver resolver = new DefaultBearerTokenResolver();
resolver.setAllowUriQueryParameter(true);
http.authorizeRequests()
.anyRequest().authenticated()
.and().oauth2ResourceServer().bearerTokenResolver(resolver)
.jwt();
谢谢。