You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

微服务架构下Kong JWT认证授权相关技术咨询

使用Kong实现统一JWT认证的解决方案

背景概述

你当前的架构中,Kong仅作为代理与负载均衡,由Authentication Service负责生成JWT,其他服务各自解码JWT导致代码冗余。目标是通过Kong的JWT插件统一处理JWT验证与用户信息传递,消除后端服务的重复解码逻辑。


1. 认证服务如何与Kong对接生成包含用户数据的JWT?

Kong的JWT插件不负责生成JWT令牌,它的核心作用是验证JWT的合法性。正确的对接流程如下:

  • 认证服务依然负责用户登录校验(调用user_service查询MongoDB),但生成JWT时,必须使用与Kong中对应Consumer绑定的密钥(secret)进行签名。
  • 你需要为每个用户在Kong中创建对应的Consumer,并绑定JWT密钥(jwt_secrets):
    • 静态场景(固定用户):直接在kong.yml中声明Consumer与密钥;
    • 动态场景(用户注册时自动创建):认证服务通过Kong的Admin API(/consumers和/consumers/{username}/jwt端点)创建Consumer与密钥。
  • 生成JWT时,必须在Payload中包含kid字段(对应Kong中jwt_secrets的key值),以及用户标识(如sub存用户ID、username存用户名),这样Kong才能关联到对应的Consumer并完成验证。

2. Kong是否需要连接数据库以获取用户数据并生成密钥?

  • 如果你使用当前的DB-less模式(KONG_DATABASE: 'off'),不需要连接数据库,所有Consumer、密钥、服务路由都通过kong.yml定义,或通过Admin API写入内存(重启后需同步到配置文件才能持久化)。
  • 如果是数据库模式(如PostgreSQL/Cassandra),Kong会将Consumer、密钥等数据存储到数据库,适合动态创建用户的场景(比如用户注册时自动生成Kong凭证)。
  • 注意:Kong本身不生成密钥,密钥需要你在创建Consumer的JWT凭证时指定,或让Kong自动生成(通过Admin API创建时不指定secret,Kong会生成随机值)。

3. 如何通过Kong解码JWT并传递到其他服务的请求头?

Kong的JWT插件支持将解码后的JWT声明(claims)添加到请求头中,传递给后端服务。只需在插件配置中开启claims_to_headers选项,指定要映射的声明与请求头:

plugins:
  - name: jwt
    enabled: true
    protocols: [http, https]
    config:  
      key_claim_name: kid
      claims_to_verify: [exp]
      claims_to_headers: # 配置声明到请求头的映射
        - sub: X-User-ID
        - username: X-User-Name
        - role: X-User-Role

后端服务直接读取这些请求头即可,无需再解码JWT。

4. 实现示例(基于你的DB-less模式)

步骤1:更新kong.yml,添加Consumer与JWT密钥

_format_version: "3.0"
_transform: true

services:
  # 保留你原有的服务配置
  - name: building_service
    url: http://building_service/building
    routes:
    - name: building_service_route
      paths: [/building]
  - name: user_service
    url: http://user_service/user
    routes:
    - name: user_service_route
      paths: [/user]
  # ...其他服务省略

consumers:
  - username: user_001 # 对应用户系统的用户ID/用户名
    jwt_secrets:
      - key: user_001_kid # 对应JWT中的kid字段
        secret: user_001_secret_key # 签名密钥,认证服务生成JWT时需使用

plugins:
  - name: jwt
    enabled: true
    protocols: [http, https]
    config:  
      key_claim_name: kid
      claims_to_verify: [exp]
      claims_to_headers:
        - sub: X-User-ID
        - username: X-User-Name
  - name: bot-detection
  - name: rate-limiting
    config:
      minute: 60
      policy: local

步骤2:认证服务生成JWT的伪代码

import jwt
import time

def generate_user_jwt(user_id, username):
    payload = {
        "kid": "user_001_kid",  # 对应Kong中jwt_secrets的key
        "sub": user_id,
        "username": username,
        "exp": time.time() + 3600  # 过期时间1小时
    }
    secret = "user_001_secret_key"  # 对应Kong中jwt_secrets的secret
    return jwt.encode(payload, secret, algorithm="HS256")

步骤3:后端服务获取用户信息示例(Java)

// 直接读取Kong传递的请求头
String userId = request.getHeader("X-User-ID");
String username = request.getHeader("X-User-Name");

步骤4:动态创建Consumer(用户注册场景)

用户注册成功后,认证服务调用Kong Admin API创建对应凭证:

# 创建Consumer
curl -X POST http://localhost:8001/consumers \
  --data "username=new_user_002"

# 绑定JWT密钥
curl -X POST http://localhost:8001/consumers/new_user_002/jwt \
  --data "key=new_user_002_kid" \
  --data "secret=new_user_002_secret"

5. 你是否存在误解?

你的核心需求(统一JWT验证、消除后端解码冗余)完全可以实现,但有一个关键误解:Kong的JWT插件不负责生成JWT令牌,只负责验证JWT的合法性。之前教程中的“单个Consumer生成JWT”,指的是创建JWT凭证(密钥对),而非生成实际的JWT令牌。

调整后的正确流程:

  1. 用户登录 → 认证服务校验用户 → 使用Kong对应Consumer的密钥生成JWT → 返回给用户
  2. 用户携带JWT请求后端服务 → Kong验证JWT合法性 → 解码claims并添加到请求头 → 转发给后端服务
  3. 后端服务直接读取请求头获取用户信息,无需处理JWT

内容的提问来源于stack exchange,提问作者Ignac96

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:30:53