Feign 接口调用使用

以新创建的 demo 模块为例,需要在 spi 配置如下类的全路径

Feign 调用包含 feign-client、spi 定义两个部分

// feign-client
@FeignClient(contextId = "remoteDemoService", value = "demo-biz")
public interface RemoteDemoService {
}

配置 feignclient 路径:demo-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports

com.pig4cloud.pig.demo.api.feign.RemoteDemoService

带 Token 请求

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

无 Token 请求

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

FeignClient 需要带一个请求 token,FROM_IN 声明是内部调用

remoteLogService.saveLog(sysLog, SecurityConstants.FROM_IN);

目标接口对内外调用进行限制添加 @Inner 注解,这样就避免接口对外暴露的安全问题。只能通过内部调用才能使用,浏览器不能直接访问该接口

@Inner
@PostMapping
public R save(@Valid @RequestBody SysLog sysLog) {
    return new R<>(sysLogService.save(sysLog));
}

若代码无法加 @Inner 也可以参考 API 对外暴露章节对外暴露目标接口

核心代码

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

public class PigFeignClientInterceptor extends OAuth2FeignRequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        Collection<String> fromHeader = template.headers().get(SecurityConstants.FROM);
        if (CollUtil.isNotEmpty(fromHeader) && fromHeader.contains(SecurityConstants.FROM_IN)) {
            return;
        }

        accessTokenContextRelay.copyToken();
        if (oAuth2ClientContext != null
            && oAuth2ClientContext.getAccessToken() != null) {
            super.apply(template);
        }
    }
}

♥️ 获取支持

遇到问题?

如果您在使用过程中遇到任何问题、有功能建议或需求,请点击此卡片前往 Gitee 仓库提交 Issue。