spring安全上下文通过webclient未来链传播

zynd9foi  于 2021-10-10  发布在  Java
关注(0)|答案(0)|浏览(216)

tldr:安全上下文不会传播到由生成的链接未来 Mono.toFuture() 发出webclient请求时。
我有一个web应用程序,它使用SpringSecurityOAuth2在控制器上强制执行授权。该应用程序使用spring Responsive webclient将异步https请求编排到其他几个下游API,其中一个“repositorya”要求将调用者提供的令牌传播到下游调用。
为了简单地解释这一点,编排这些调用的服务如下所示:

public CompletableFuture<Model> doSomething(String id) {
        return repositoryA.get(id)
            .thenCompose(repositoryB::action)
            .thenCompose(repositoryA::fulfill);
}

repositorya和repositoryb各自使用自己的 WebClient ,repositoryb通过一组客户端凭据处理其自己的下游身份验证。
存储库方法如下所示:

public CompletableFuture<Model> get(Stringid) {
        return webClient.get()
            .uri(b -> b.pathSegment(PATH, id.toString()).build())
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToMono(Model.class)
            .toFuture();
}

repositorya的webclient使用筛选器将令牌作为安全上下文的头进行传播

public class DelegatingSecurityExchangeFilter implements ExchangeFilterFunction {

    static final String SECURITY_CONTEXT_ATTRIBUTES = "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES";

    @Override
    public Mono<ClientResponse> filter(ClientRequest clientRequest, ExchangeFunction next) {
        return Mono.deferContextual(view -> next.exchange(RequestWithBearer(clientRequest, getToken(view))));
    }

    private OAuth2AccessToken getToken(ContextView view) {
        Map<Class<?>, Object> springCtx = view.get(SECURITY_CONTEXT_ATTRIBUTES);
        Authentication auth = (Authentication) springCtx.get(Authentication.class);
        return (OAuth2AccessToken) auth.getCredentials();
    }

    private ClientRequest RequestWithBearer(ClientRequest request, AbstractOAuth2Token token) {
        return ClientRequest.from(request)
            .headers(headers -> headers.setBearerAuth(token.getTokenValue()))
            .build();
    }

}

这在第一种情况下效果很好 repositoryA.get(id) 调用,但调试时我可以看到第一次 .toFuture() 在存储库方法中,安全上下文不会传播到下一个线程。
我已经研究了这里的许多概念,但到目前为止还没有成功,我假设被动webclient不使用相同的机制为其事件循环生成线程。 SecurityReactorContextConfiguration 看起来它应该在做这项工作,但它只有在subscribe上已有线程本地上下文时才起作用。
更多背景:
https://github.com/spring-projects/spring-framework/issues/25710

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题