⭐️ feign 接口调用使用

:::info 以新创建的demo 模块为例,需要在 spring.factories 配置如下三个类的全路径 :::

  • feign 调用包含 feign-client、 异常回调、降级逻辑实现 三个部分 ```java // feign-client @FeignClient(contextId = “remoteDemoService”, value = “demo-biz”,
    1. fallbackFactory = RemoteDemoServiceFallbackFactory.class)
    public interface RemoteDemoService { }

// 接口降级实现 降级逻辑实现 public class RemoteDemoServiceFallbackImpl implements RemoteDemoService { @Setter private Throwable cause; }

// 异常回调工厂 public class RemoteDemoServiceFallbackFactory implements FallbackFactory { @Override public RemoteDemoServiceFallbackImpl create(Throwable throwable) { RemoteDemoServiceFallbackImpl remoteLogServiceFallback = new RemoteDemoServiceFallbackImpl(); RemoteDemoServiceFallbackImpl.setCause(throwable); return remoteLogServiceFallback; } }

  1. - demo-api/src/main/resources/META-INF/spring.factories
  2. ```java
  3. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  4. com.pig4cloud.pig.demo.api.feign.factory.RemoteDemoServiceFallbackFactory,\
  5. com.pig4cloud.pig.demo.api.feign.fallback.RemoteDemoServiceFallbackImpl

① 客户端带Token 情况

  1. 如下图客户端携带token访问A服务。
  2. A服务通过FeginClient 调用B服务获取相关依赖数据。
  3. 所以只要带token 访问A 无论后边链路有多长 ABCD 都可以获取当前用户信息
  4. 权限需要有这些整个链路接口的全部权限才能成功

feign调用及服务间鉴权 - 图1

② 无token请求,服务内部发起情况处理

feign调用及服务间鉴权 - 图2

:::warning 很多情况下,比如定时任务。A服务并没有token 去请求B服务,pig也对这种情况进行了兼容。类似于A对外暴露API,但是又安全限制 :::

  • FeignClient 需要带一个请求token,FROM_IN 声明是内部调用
  1. remoteLogService.saveLog(sysLog, SecurityConstants.FROM_IN);

image.png

  • 目标接口对内外调用进行限制添加 @Inner 注解,这样就避免接口对外暴露的安全问题。只能通过内部调用才能使用,浏览器不能直接访问该接口
  1. @Inner
  2. @PostMapping
  3. public R save(@Valid @RequestBody SysLog sysLog) {
  4. return new R<>(sysLogService.save(sysLog));
  5. }
  • 若代码无法加 @Inner 也可以参考API 对外暴露章节对外暴露目标接口

③ 核心代码

fein 拦截器将本服务的token 通过copyToken的形式传递给下游服务

  1. public class PigFeignClientInterceptor extends OAuth2FeignRequestInterceptor {
  2. @Override
  3. public void apply(RequestTemplate template) {
  4. Collection<String> fromHeader = template.headers().get(SecurityConstants.FROM);
  5. if (CollUtil.isNotEmpty(fromHeader) && fromHeader.contains(SecurityConstants.FROM_IN)) {
  6. return;
  7. }
  8. accessTokenContextRelay.copyToken();
  9. if (oAuth2ClientContext != null
  10. && oAuth2ClientContext.getAccessToken() != null) {
  11. super.apply(template);
  12. }
  13. }
  14. }

❤ 问题咨询

手势点击蓝字求关注简约风动态引导关注__2022-09-07+23_18_38.gif