如何区分 RequestInterceptor 中 two/multiple 端点之间的 headers

How to differentiate headers between two/multiple endpoints in a RequestInterceptor

您好,我是 Java 和 Springboot 的新手。我目前正在使用 API,在发出 POST 请求之前,我需要生成一个 Bearer 令牌。为了生成 Bearer 令牌,我需要将我的基本身份验证凭据传递到“/oauth/token”端点。我的应用程序在传递我的基本身份验证凭据时遇到问题,因为当我点击“/v1/some-endpoint”时,我被拒绝授权,因为 Bearer 令牌为空。

这是我最初的解决方案,我认为我可以检查拦截器中的 url,然后执行以下行,但在调试之后,它似乎并没有命中该行。

有什么我遗漏或没有正确实施的吗?我是否没有正确实施 Basic Auth 端点?如果您需要更多信息,请与我们联系。谢谢

@Profile("!offline")
@FeignClient(
value = "someClient",
url = "${someProperty.url}",
configuration = SomeClient.SomeClientConfig.class)
public interface someClient {

  @PostMapping("/v1/some-endpoint")
  void redeemSomething(someRequestBody data);

  @PostMapping("/oauth/token")
  static BasicAuthResponse getBasicAuthToken() {
   return new BasicAuthResponse();
 }

@AllArgsConstructor
class SomeClientConfig extends BaseClientConfig {

private final SomeProperties properties;


private final SomeAuthTokenSupplier tokenSupplier = new SomeAuthTokenSupplier();

@Bean
@Override
public CloseableHttpClient apacheClient() {
  return apacheClientFactory(properties.getUseProxy());
}

@Bean
public RequestInterceptor someAuthInterceptor() {

  return template -> {

    if(template.url().equals("/oauth/token")) {
      String authToken = Base64Utils.encodeToString((properties.getCredentials().getUser() + ":" + properties.getCredentials().getUser()).getBytes(Charset.forName("UTF-8")));
      template.header("Authorization", authToken);
    }

    template.header("Authorization", String.format("Bearer %s", tokenSupplier.getToken()));

  };
}

private class SomeAuthTokenSupplier {
  private volatile String token;
  private volatile long retrievedOn = -1L;

  String getToken() {

    if (updateTokenRequired()) {

      synchronized (this) {
        if (updateTokenRequired()) {

          BasicAuthResponse tokenResponse = getBasicAuthToken();
          token = tokenResponse.getAccess_token(); // new token from some api should be assigned here
          retrievedOn = Instant.now().toEpochMilli();
        }
      }
    }

    return token;
  }

  private boolean updateTokenRequired() {
    return  token == null || LocalDateTime.now().minusHours(8L).isAfter(LocalDateTime.ofInstant(Instant.ofEpochMilli(retrievedOn), ZoneId.systemDefault()));
  }

}

@Override
public Retryer retryer() {
  return new ClientRetry(250L, 2, 3) {
    @Override
    public void continueOrPropagate(RetryableException e) {
      if (e.status() == 401 || e.status() == 403) {
        tokenSupplier.token = null;
      }
      super.continueOrPropagate(e);
    }

    };
   }
  }
 }

值得使用标准 Spring 安全 OAuth2 客户端功能来支持 Feign 客户端中的授权

查看文档和代码示例:https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2client

更新

查看另一个代码示例:https://github.com/int128/feign-oauth2-example

如果多个服务端点需要不同的身份验证,那么值得拥有多个 Fe​​ign 客户端,每个客户端都有自己的配置