Spring Cloud OpenFeign 拦截器与认证传递

部署运行你感兴趣的模型镜像

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

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

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

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

feignClient.getUser(token, id);

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

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


⚙️ 二、基础环境

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

服务名称功能端口
user-service被调用方,验证 Token8081
order-service调用方,自动注入 Token8082

🧩 三、拦截器机制原理

Feign 提供了接口:

public interface RequestInterceptor {
    void apply(RequestTemplate template);
}

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

简单来说:

调用 Feign → 拦截器自动注入 Header → 发出 HTTP 请求

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

🔧 1️⃣ 创建拦截器类

order-service 中新建:

FeignAuthInterceptor.java

@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

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

@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

@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️⃣ 测试效果

请求:

curl -H "Authorization: Bearer test-token" http://localhost:8082/orders/1

返回:

订单已创建,用户:张三-1

如果不传 Token:

{
  "status": 401,
  "error": "Unauthorized",
  "message": "无效的Token"
}

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


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

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

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

String traceId = MDC.get("traceId");
if (traceId == null) {
    traceId = UUID.randomUUID().toString();
    MDC.put("traceId", traceId);
}
template.header("X-Trace-Id", traceId);

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

logging:
  pattern:
    console: "%d{HH:mm:ss.SSS} [%X{traceId}] %-5level %logger{36} - %msg%n"

效果示例:

11:15:03.123 [abc12345] INFO  c.e.o.client.UserClient  - 调用用户服务成功

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


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

场景说明示例
🔐 认证透传自动传递 JWT / OAuth2 TokenAuthorization
🧩 链路追踪自动生成 TraceId 并传递X-Trace-Id
🌏 多语言自动带上用户语言环境Accept-Language
🧱 灰度流量自动标记灰度标识X-Env: gray
🧰 日志追踪在 MDC 中注入 Feign 目标信息MDC.put("feign.target", template.url())

🪄 七、完整调用链示意图

用户请求 OrderService Feign拦截器 Feign客户端 UserService 带 Authorization Header 的请求 设置 Token 到上下文 注入 Authorization + TraceId GET /users/1 返回用户信息 返回 UserDTO 订单已创建 用户请求 OrderService Feign拦截器 Feign客户端 UserService

实用小工具

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

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@井九

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值