如何使用自定义身份验证 header 和 spring 引导 oauth2 资源服务器
How to use custom auth header with spring boot oauth2 resource server
我正在配置 spring 云 api 网关以支持多个安全链。为此,我使用了几个安全过滤器链,这些链在特定安全性 header presence:
上触发
- 已经使用授权的旧版本header
- 以及与外部 idp 集成的新实现。该解决方案利用资源服务功能。对于我想使用的这条链,可以说“New-Auth”header.
如果我调整当前设置以在授权 header 存在时触发第二个 (idp) 链(并使用 IDP 令牌进行调用),那么一切正常。通过这种方式,安全链会根据 idp jwk 验证它在 Authorization header 中期望的令牌。但是这个 header 已经为遗留身份验证保留。
我想我需要一种方法来指向 spring 资源服务器链一个新的 header 名称来查找。
我的安全依赖项:
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
我的配置
@EnableWebFluxSecurity
public class WebSecurityConfiguration {
// ...
@Bean
@Order(1)
public SecurityWebFilterChain iamAuthFilterChain(ServerHttpSecurity http) {
ServerWebExchangeMatcher matcher = exchange -> {
HttpHeaders headers = exchange.getRequest().getHeaders();
List<String> strings = headers.get(SurpriseHeaders.IDP_AUTH_TOKEN_HEADER_NAME);
return strings != null && strings.size() > 0
? MatchResult.match() : MatchResult.notMatch();
};
http
.securityMatcher(matcher)
.csrf().disable()
.authorizeExchange()
.pathMatchers(navigationService.getAuthFreeEndpoints()).permitAll()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer(OAuth2ResourceServerSpec::jwt)
.oauth2ResourceServer().jwt().jwkSetUri(getJwkUri())
.and()
.and()
.addFilterAt(new LoggingFilter("idpAuthFilterChain"), SecurityWebFiltersOrder.FIRST)
.addFilterAfter(new IdpTokenExchangeFilter(authClientService), SecurityWebFiltersOrder.AUTHENTICATION)
;
return http.build();
}
}
肮脏的解决方案:
我们可以添加一些过滤器来编辑请求,并在 security filter chain
的开头复制传入的“New-Auth”header 作为“授权”header。
看起来可行,但我相信这应该是更好的方法。
您可以为 oauth2ResourceServer
配置指定 ServerAuthenticationConverter
,如下所示:
http
.oauth2ResourceServer((resourceServer) -> resourceServer
.bearerTokenConverter(customBearerTokenAuthenticationConverter())
.jwt()
);
ServerAuthenticationConverter customBearerTokenAuthenticationConverter() {
ServerBearerTokenAuthenticationConverter tokenAuthenticationConverter = new ServerBearerTokenAuthenticationConverter();
tokenAuthenticationConverter.setBearerTokenHeaderName("New-Auth");
return tokenAuthenticationConverter;
}
我正在配置 spring 云 api 网关以支持多个安全链。为此,我使用了几个安全过滤器链,这些链在特定安全性 header presence:
上触发- 已经使用授权的旧版本header
- 以及与外部 idp 集成的新实现。该解决方案利用资源服务功能。对于我想使用的这条链,可以说“New-Auth”header.
如果我调整当前设置以在授权 header 存在时触发第二个 (idp) 链(并使用 IDP 令牌进行调用),那么一切正常。通过这种方式,安全链会根据 idp jwk 验证它在 Authorization header 中期望的令牌。但是这个 header 已经为遗留身份验证保留。
我想我需要一种方法来指向 spring 资源服务器链一个新的 header 名称来查找。
我的安全依赖项:
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
我的配置
@EnableWebFluxSecurity
public class WebSecurityConfiguration {
// ...
@Bean
@Order(1)
public SecurityWebFilterChain iamAuthFilterChain(ServerHttpSecurity http) {
ServerWebExchangeMatcher matcher = exchange -> {
HttpHeaders headers = exchange.getRequest().getHeaders();
List<String> strings = headers.get(SurpriseHeaders.IDP_AUTH_TOKEN_HEADER_NAME);
return strings != null && strings.size() > 0
? MatchResult.match() : MatchResult.notMatch();
};
http
.securityMatcher(matcher)
.csrf().disable()
.authorizeExchange()
.pathMatchers(navigationService.getAuthFreeEndpoints()).permitAll()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer(OAuth2ResourceServerSpec::jwt)
.oauth2ResourceServer().jwt().jwkSetUri(getJwkUri())
.and()
.and()
.addFilterAt(new LoggingFilter("idpAuthFilterChain"), SecurityWebFiltersOrder.FIRST)
.addFilterAfter(new IdpTokenExchangeFilter(authClientService), SecurityWebFiltersOrder.AUTHENTICATION)
;
return http.build();
}
}
肮脏的解决方案:
我们可以添加一些过滤器来编辑请求,并在 security filter chain
的开头复制传入的“New-Auth”header 作为“授权”header。
看起来可行,但我相信这应该是更好的方法。
您可以为 oauth2ResourceServer
配置指定 ServerAuthenticationConverter
,如下所示:
http
.oauth2ResourceServer((resourceServer) -> resourceServer
.bearerTokenConverter(customBearerTokenAuthenticationConverter())
.jwt()
);
ServerAuthenticationConverter customBearerTokenAuthenticationConverter() {
ServerBearerTokenAuthenticationConverter tokenAuthenticationConverter = new ServerBearerTokenAuthenticationConverter();
tokenAuthenticationConverter.setBearerTokenHeaderName("New-Auth");
return tokenAuthenticationConverter;
}