【问题标题】:Best way to add a RequestInterceptor to a single FeignClient将 RequestInterceptor 添加到单个 FeignClient 的最佳方法
【发布时间】:2021-12-30 22:44:41
【问题描述】:

我需要将RequestInterceptor 添加到特定的 feign 客户端。拦截器将添加我不想泄露给第三方的身份验证信息,因此我不希望它为所有 Feign 客户端触发。我有这个工作,但这似乎有点混乱,我希望有一个更清洁(更少代码)的选项。

我希望有人能指出我可以简化事情的地方。特别是围绕编码器/解码器的东西。我真的不喜欢他们像那样把我的服务构造函数弄得乱七八糟,而且觉得奇怪的是他们甚至需要一开始就被指定。

我有

// build.gradle
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

我有一个 RequestInterceptor

import feign.RequestInterceptor;
import feign.RequestTemplate;

public class BearerAuthRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        // ... SNIP ... (just adds an Authorization header)
    }
}

我有一个 FeignClient

@FeignClient(name = "myfeignclient")
public interface MyFeignClient {
    @GetMapping(value = "/doTheThing")
    String doTheThing();
}

我从这样的服务中使用我的 FeignClient:

@Service
@Import(FeignClientsConfiguration.class)
public class MyService {

  private final MyFeignClient myFeignClient;

  @Autowired
  public MyService(Decoder decoder, Encoder encoder, Contract contract) {
    this.myFeignClient = Feign.builder()
                    .contract(contract)
                    .encoder(encoder)
                    .decoder(decoder)
                    .requestInterceptor(new BearerAuthRequestInterceptor())
                    .target(MyFeignClient.class, "https://whatever.com");
  }

  public void callTheFeignClient() {
      myFeignClient.doTheThing();
  }
}

【问题讨论】:

    标签: spring-cloud-feign feign


    【解决方案1】:

    感谢this 的评论,我设法稍微整理了我的实现。所以不再需要指定编码/解码器废话,或者必须手动构建我的 Feign 客户端。

    文档here 提供了一些信息,但通常它们在具体示例上有点薄,所以以下内容可能对其他人有所帮助。注意:我使用的是 spring boot,并在 build.gradle implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' 中包含 feign

    首先,像这样创建RequestInterceptor

    import org.springframework.context.annotation.Bean;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.oauth2.jwt.Jwt;
    
    import feign.RequestInterceptor;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * A Feign configuration to add the incoming Bearer token to an outgoing feign client request.
     * Only annotate this class with "@Configuration" if you want this interceptor to apply globally to all your Feign clients.
     * Otherwise you risk exposing the auth token to a third party, or adding it unnecessarily to requests that don't need it.
     */
    @Slf4j
    public class BearerAuthFeignConfig {
    
        @Bean
        public RequestInterceptor bearerAuthRequestInterceptor() {
            return requestTemplate -> {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                if (authentication != null && authentication.getPrincipal() instanceof Jwt) {
                    Jwt jwt = (Jwt) authentication.getPrincipal();
                    requestTemplate.header("Authorization", "Bearer " + jwt.getTokenValue());
                } else {
                    log.error("Unable to add Authoriation header to Feign requestTemplate");
                }
            };
        }
    }
    
    

    然后在声明你的feign客户端时,传递配置

    @FeignClient(
        name = "my-client-that-needs-the-auth",
        configuration = BearerAuthFeignConfig.class,
        url = "http://whatever.com"
    )
    public interface PlayerManagementClient {
      ...
    

    您还需要 @SpringBootApplication 类上的 @EnableFeignClients 注释

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-09
      • 2018-08-10
      相关资源
      最近更新 更多