Spring WebClient 在标头中设置不记名身份验证令牌

med*_*ech 6 webclient oauth spring-webclient

以下场景:

我有两个微服务 A 和 B。服务 A 是一个承载客户端,它有一个开放的 api 并接收来自必须由 keycloak 授权的客户端的请求。现在我想从服务 A 向服务 B 发送一个授权请求,它也是一个承载客户端。

我想过在 webclient builder 过程中将功能添加为过滤器功能,例如

    @Bean
    WebClient webClient() {
        return WebClient.builder()
                .filter(authHeader())
                .build();
    }

    private ExchangeFilterFunction authHeader(String token) {
        return (request, next) -> next.exchange(ClientRequest.from(request).headers((headers) -> {
            headers.setBearerAuth(token);
        }).build());
    }
Run Code Online (Sandbox Code Playgroud)

这是我在另一个问题中找到的一个例子。这对我来说似乎是正确的方法,但我可以在配置的那个阶段提供“字符串令牌”参数吗?我只是从 RestTemplate 切换到 Webclient,很抱歉,这是一个转储问题。

编辑:我可以在构建新的 Webclient 时手动设置标题。

return WebClient.builder().defaultHeader("Authorization", "Bearer "+ context.getTokenString()).build();
Run Code Online (Sandbox Code Playgroud)

正如我从 RestTemplate 知道的,它可以用作单例。还有一个 KeyCloakRestTemplate 会自动注入标头。

Webclient 是不可变的,所以当我注入它时,我不能只使用它并在之后添加标头。此外,我无法在启动时设置此标头,因为我必须等待获取承载标头并将其传入的请求。所以我想除了这样做之外没有其他方法吗?

mem*_*und 8

或者直接在发送过程中设置:

webClient.get()
    .uri(url)
    .headers(h -> h.setBearerAuth(token))
    .retrieve();
Run Code Online (Sandbox Code Playgroud)


M. *_*tin 5

我最终ExchangeFilterFunction在类似的情况下使用了过滤器。就我而言,我有一个 Spring 组件,它检索要使用的令牌。如果context您的示例中context.getTokenString()是 Spring bean,您应该能够执行相同的操作:

@Bean
WebClient webClient(SomeContext context) {
    return WebClient.builder()
            .filter((request, next) -> next.exchange(
                    withBearerAuth(request, context.getTokenValue())))
            .build();
}

private static ClientRequest withBearerAuth(ClientRequest request, 
                                            String token) {
    return ClientRequest.from(request)
            .header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
            .build();
}
Run Code Online (Sandbox Code Playgroud)