使用spring-boot-starter-oauth2-client时如何配置bearer-only = true

Posted

技术标签:

【中文标题】使用spring-boot-starter-oauth2-client时如何配置bearer-only = true【英文标题】:How to configure bearer-only = true when Using spring-boot-starter-oauth2-client 【发布时间】:2021-01-13 14:49:06 【问题描述】:

我正在尝试使用 keycloak 在 spring 云网关中为我的 rest api 设置 o auth2 身份验证。 keyclcoak 将我的请求重定向到登录页面,同时将访问令牌作为不记名令牌传递。在许多地方,我发现解决方案是在 keycloak 适配器中设置 bearer-only = true 。使用 spring-boot-starter-oauth2-client 时在哪里设置它。我不能使用 keycloak-spring-boot-starter 在 application.yml 中设置它

谢谢

【问题讨论】:

是什么让你想使用 spring-security-oauth2-client?客户端模块用于通过 OAuth 2.0 授权流程获取令牌。您正在构建的网关如何知道令牌是什么?如果只是在Authorization 标头中将其提供给网关,那么 spring-security-oauth2-resource-server 就是这样做的。 @jzheaux 我正在尝试在网关中为在它后面运行的服务进行身份验证。我设置了一个具有领域、用户和角色的密钥锁服务器,通过我的令牌端点,我可以获得 oauth2 令牌。我想将此令牌与请求一起传递并在网关中进行身份验证。我是这个 spring 框架的新手。 谢谢,这很有帮助。你如何将令牌传递给网关?例如,调用者是否以Authorization 标头将其交给网关? 【参考方案1】:

我和你有同样的问题。没有找到答案,我开发了一个带有轻量级 keycloak 客户端的过滤器,它调用 keycloak 的 Endpoint introspect 来验证令牌

客户:

public class KeycloakClient 

private final KeycloakConfigurationProperties kcProperties;
private final WebClient client;

public KeycloakClient(final KeycloakConfigurationProperties keycloakConfigurationProperties) 
    this.kcProperties = keycloakConfigurationProperties;
    this.client = WebClient.builder()
                           .baseUrl(keycloakConfigurationProperties.getAuth_server_url())
                           .filter(logRequest())
                           .build();


public Mono<Boolean> validateBearerToken(String bearerToken) 
    //todo: improve error management
    return prepareAndRunRequest(bearerToken).retrieve()
                                            .bodyToMono(KeycloakValidationResponse.class)
                                            .flatMap(response -> Mono.just(response.getActive()))
                                            .onErrorResume(WebClientResponseException.class,
                                                           ex -> Mono.just(false));


private WebClient.RequestHeadersSpec<?> prepareAndRunRequest(String bearerToken) 

    return client.post()
                 .uri(uriBuilder -> uriBuilder.path("/auth/realms/")
                                              .path(kcProperties.getRealm())
                                              .path("/protocol/openid-connect/token/introspect")
                                              .build())
                 .contentType(MediaType.APPLICATION_JSON)
                 .body(BodyInserters.fromFormData("client_id", kcProperties.getResource())
                                    .with("client_secret", kcProperties.getCredentials_secret())
   

过滤器:

public class ValidationTokenGatewayFilterFactory extends AbstractGatewayFilterFactory<ValidationTokenGatewayFilterFactory.Config> 

private final KeycloakClient client;

public ValidationTokenGatewayFilterFactory(KeycloakClient client) 
    super(Config.class);
    this.client = client;


@Override
public GatewayFilter apply(Config config) 
    return (exchange, chain) -> 

        String token = exchange.getRequest()
                               .getHeaders()
                               .get(AUTHORIZATION)
                               .get(0);

        token = token.substring(7);

        log.trace("-- ValidationToken(): token=", token);

        return client.validateBearerToken(token)
                     .flatMap(validated -> 
                         if (validated) 
                             log.debug("-- ValidationToken(): Token valid");
                             return chain.filter(exchange);
                          else 
                             log.debug("-- ValidationToken(): Token invalid");
                             exchange.getResponse()
                                     .setStatusCode(HttpStatus.UNAUTHORIZED);

                             return exchange.getResponse()
                                            .setComplete();
                         
                     );
    ;


public static class Config 

您可以在此处找到完整示例:https://gitlab.com/-/snippets/2105967

【讨论】:

以上是关于使用spring-boot-starter-oauth2-client时如何配置bearer-only = true的主要内容,如果未能解决你的问题,请参考以下文章

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份