首页 > 解决方案 > Spring boot:Feign客户端休息调用不适用于oauth2,但可以在浏览器上使用

问题描述

有 2 个微服务,一个休息服务,一个是 websocket 服务。Websocket 服务有假装客户端与其余服务对话。

从浏览器工具(例如邮递员)调用休息服务时,调用正常工作。我们只传递Authorization带有值的标头Bearer XXXXX

当从没有拦截器的 feign 调用时,我们会得到 401:未授权,这是正确的行为。

当将此拦截器添加到代码库时,因为 XXXXX 是真正的令牌,当然,我们会收到 403

@Component
public class FeignOauth2Interceptor implements RequestInterceptor {
    private static final String AUTHORIZATION_HEADER = "Authorization";   
    @Override
    public void apply(RequestTemplate template) {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = 
        securityContext.getAuthentication();
        template.header(AUTHORIZATION_HEADER, "Bearer XXXXX");
    }
}

拦截器被调用,因为我们在添加后看到不同的错误代码,我们从 401 变为 403。

我们在这里缺少什么?

提前致谢

标签: springspring-bootoauth-2.0access-deniedfeign

解决方案


我认为在拦截器中硬编码令牌不是一个好主意,您可以从OAuth2AuthenticationDetails获取令牌:

@Bean
public RequestInterceptor requestTokenBearerInterceptor() {

    return new RequestInterceptor() {
        @Override
        public void apply(RequestTemplate requestTemplate) {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if(authentication == null) return;
            OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
            requestTemplate.header("Authorization", "Bearer " + details.getTokenValue());                   
        }
    };
}

此外,您可以使用OAuth2FeignRequestInterceptor,它从上下文中获取您的令牌并在需要时自行刷新它。在我看来,这是一个更好的解决方案。您可以在此处找到使用它的示例:https ://stackoverflow.com/a/53454703/10697598


推荐阅读