首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Spring Cloud OpenFeign 拦截器与认证传递

Spring Cloud OpenFeign 拦截器与认证传递

作者头像
井九
发布2025-10-31 08:42:47
发布2025-10-31 08:42:47
4220
举报
文章被收录于专栏:四楼没电梯四楼没电梯

💡 一、为什么要用 Feign 拦截器?

在微服务架构中,一个请求往往会从「网关 → 服务 A → 服务 B → 服务 C」层层传递。 这时通常会涉及两个关键问题:

  1. 认证 Token(JWT)如何跨服务自动传递?
  2. TraceId、RequestId 等链路追踪信息如何在调用链中保留?

如果你不用 Feign 拦截器,就得在每个接口调用处手动添加:

代码语言:javascript
复制
feignClient.getUser(token, id);

这不仅麻烦,还容易出错。

Feign 拦截器(RequestInterceptor) 可以让你一次配置,全局生效。 所有 Feign 请求都会自动带上所需 Header。


⚙️ 二、基础环境

依旧延续上篇的两个服务结构:

服务名称

功能

端口

user-service

被调用方,验证 Token

8081

order-service

调用方,自动注入 Token

8082


🧩 三、拦截器机制原理

Feign 提供了接口:

代码语言:javascript
复制
public interface RequestInterceptor {
    void apply(RequestTemplate template);
}

Spring Cloud 会自动扫描所有实现该接口的 Bean,在发出 Feign 请求前调用。

简单来说:

代码语言:javascript
复制
调用 Feign → 拦截器自动注入 Header → 发出 HTTP 请求

🧱 四、示例一:自动传递 Token(JWT)

🔧 1️⃣ 创建拦截器类

order-service 中新建:

FeignAuthInterceptor.java

代码语言:javascript
复制
@Component
public class FeignAuthInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        // 模拟从上下文中获取 token(实际可从 ThreadLocal 或 SecurityContext 中取)
        String token = UserContextHolder.getToken();

        if (StringUtils.hasText(token)) {
            template.header("Authorization", "Bearer " + token);
        }

        // 添加全局 TraceId(例如 Sleuth 生成)
        String traceId = MDC.get("traceId");
        if (traceId != null) {
            template.header("X-Trace-Id", traceId);
        }
    }
}

🔧 2️⃣ 模拟上下文存储 Token

order-service 中添加一个简单的上下文工具类:

UserContextHolder.java

代码语言:javascript
复制
public class UserContextHolder {
    private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();

    public static void setToken(String token) {
        CONTEXT.set(token);
    }

    public static String getToken() {
        return CONTEXT.get();
    }

    public static void clear() {
        CONTEXT.remove();
    }
}

🔧 3️⃣ 控制器中设置 Token

OrderController.java

代码语言:javascript
复制
@RestController
@RequiredArgsConstructor
@RequestMapping("/orders")
public class OrderController {

    private final UserClient userClient;

    @GetMapping("/{userId}")
    public String createOrder(@PathVariable Long userId, @RequestHeader("Authorization") String authHeader) {
        // 将用户请求头的 Token 注入上下文
        UserContextHolder.setToken(authHeader);

        UserDTO user = userClient.getUserById(userId);
        UserContextHolder.clear();

        return "订单已创建,用户:" + user.getName();
    }
}

🧰 4️⃣ 被调用方验证 Token

user-service → UserController.java

代码语言:javascript
复制
@GetMapping("/{id}")
public UserDTO getUserById(@PathVariable Long id, @RequestHeader("Authorization") String token) {
    if (!"Bearer test-token".equals(token)) {
        throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "无效的Token");
    }
    return new UserDTO(id, "张三-" + id);
}

🧪 5️⃣ 测试效果

请求:

代码语言:javascript
复制
curl -H "Authorization: Bearer test-token" http://localhost:8082/orders/1

返回:

代码语言:javascript
复制
订单已创建,用户:张三-1

如果不传 Token:

代码语言:javascript
复制
{
  "status": 401,
  "error": "Unauthorized",
  "message": "无效的Token"
}

✅ 实现了 Token 自动透传 + 校验机制


🧩 五、示例二:自动添加 TraceId(链路追踪)

在分布式链路中(例如 Zipkin / Sleuth),TraceId 用于标识一个完整请求路径。

如果你想手动实现简化版 TraceId 传递,只需在拦截器中添加:

代码语言:javascript
复制
String traceId = MDC.get("traceId");
if (traceId == null) {
    traceId = UUID.randomUUID().toString();
    MDC.put("traceId", traceId);
}
template.header("X-Trace-Id", traceId);

并在日志输出格式中打印:

代码语言:javascript
复制
logging:
  pattern:
    console: "%d{HH:mm:ss.SSS} [%X{traceId}] %-5level %logger{36} - %msg%n"

效果示例:

代码语言:javascript
复制
11:15:03.123 [abc12345] INFO  c.e.o.client.UserClient  - 调用用户服务成功

即每个请求都带有自己的 TraceId,方便排查跨服务调用问题。


🧠 六、进阶:拦截器的多场景应用

场景

说明

示例

🔐 认证透传

自动传递 JWT / OAuth2 Token

Authorization

🧩 链路追踪

自动生成 TraceId 并传递

X-Trace-Id

🌏 多语言

自动带上用户语言环境

Accept-Language

🧱 灰度流量

自动标记灰度标识

X-Env: gray

🧰 日志追踪

在 MDC 中注入 Feign 目标信息

MDC.put("feign.target", template.url())


🪄 七、完整调用链示意图


实用小工具

App Store 截图生成器应用图标生成器在线图片压缩utc timestamp, ctf toolChrome插件-强制开启复制-护眼模式-网页乱码设置编码 乖猫记账,AI智能分类的最佳聊天记账App。 Elasticsearch可视化客户端工具

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 💡 一、为什么要用 Feign 拦截器?
  • ⚙️ 二、基础环境
  • 🧩 三、拦截器机制原理
  • 🧱 四、示例一:自动传递 Token(JWT)
    • 🔧 1️⃣ 创建拦截器类
    • 🔧 2️⃣ 模拟上下文存储 Token
    • 🔧 3️⃣ 控制器中设置 Token
    • 🧰 4️⃣ 被调用方验证 Token
    • 🧪 5️⃣ 测试效果
  • 🧩 五、示例二:自动添加 TraceId(链路追踪)
  • 🧠 六、进阶:拦截器的多场景应用
  • 🪄 七、完整调用链示意图
  • 实用小工具
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档