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

如何为KrakenD网关配置Reference Token(非JWT)并对接Identity Server?

KrakenD 与 Identity Server Reference Token 集成最优方案

核心思路

KrakenD原生不支持Reference Token的解析,最优方案是通过**扩展KrakenD插件,调用Identity Server的Introspection端点(RFC 7662标准)**完成Reference Token的验证与元数据提取,再将元数据注入请求上下文,为限流、计费等逻辑提供依据。

具体实现步骤

1. 配置Identity Server的Introspection端点

  • 启用Identity Server的Introspection端点:在Identity Server的配置中确保EnableIntrospectionEndpoint设为true。

  • 创建KrakenD专属客户端:

    • 分配client_id和client_secret,设置GrantTypes为client_credentials(KrakenD以此身份调用Introspection端点)。
    • 给该客户端添加introspection权限,即在AllowedScopes中包含introspection。

    示例客户端配置(Identity Server):

    {
      "ClientId": "krakend-introspect-client",
      "ClientSecrets": [ { "Value": "<加密后的密钥>" } ],
      "AllowedGrantTypes": [ "client_credentials" ],
      "AllowedScopes": [ "introspection" ]
    }
    

2. 开发KrakenD自定义插件(Go语言)

KrakenD支持Go编写插件,核心逻辑是拦截请求、调用Introspection端点、提取元数据并注入上下文:

  • 从请求头Authorization中提取Reference Token(格式:Bearer <token>)。

  • 向Identity Server的/connect/introspect端点发送POST请求,携带KrakenD的客户端凭证和待验证的Token。

  • 解析响应,提取client_id、sub(用户ID)、exp(过期时间)等元数据。

  • 将元数据存入KrakenD的请求上下文,比如通过context.Set()或注入自定义请求头。

    简化版插件代码片段:

    package main
    
    import (
      "context"
      "net/http"
      "strings"
      "encoding/json"
    )
    
    type IntrospectionResponse struct {
      Active    bool   `json:"active"`
      ClientID  string `json:"client_id"`
      Sub       string `json:"sub"`
      Exp       int64  `json:"exp"`
    }
    
    func IntrospectMiddleware(next http.Handler) http.Handler {
      return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 提取Token
        authHeader := r.Header.Get("Authorization")
        if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
          http.Error(w, "Unauthorized", http.StatusUnauthorized)
          return
        }
        token := strings.TrimPrefix(authHeader, "Bearer ")
    
        // 调用Identity Server Introspection端点
        client := &http.Client{}
        req, _ := http.NewRequest("POST", "https://your-idp/connect/introspect", strings.NewReader("token="+token))
        req.SetBasicAuth("krakend-introspect-client", "<客户端密钥>")
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
        
        resp, err := client.Do(req)
        if err != nil || resp.StatusCode != http.StatusOK {
          http.Error(w, "Unauthorized", http.StatusUnauthorized)
          return
        }
        defer resp.Body.Close()
    
        var introspectResp IntrospectionResponse
        json.NewDecoder(resp.Body).Decode(&introspectResp)
        if !introspectResp.Active {
          http.Error(w, "Unauthorized", http.StatusUnauthorized)
          return
        }
    
        // 将元数据注入上下文
        ctx := context.WithValue(r.Context(), "client_id", introspectResp.ClientID)
        ctx = context.WithValue(ctx, "user_id", introspectResp.Sub)
        next.ServeHTTP(w, r.WithContext(ctx))
      })
    }
    

3. 集成插件到KrakenD并配置限流/计费

  • 将编译好的插件引入KrakenD配置,在extra_config中指定插件路径。
  • 配置KrakenD的限流组件,基于上下文的client_id设置差异化规则:
    {
      "endpoints": [
        {
          "endpoint": "/api/service",
          "extra_config": {
            "github.com/devopsfaith/krakend-ratelimit/juju/router": {
              "maxRate": 100,
              "clientMaxRate": 50,
              "strategy": "client_id" // 基于client_id限流
            }
          }
        }
      ]
    }
    
  • 计费逻辑可通过后续微服务读取请求上下文的client_id/user_id,统计调用次数并生成账单。

关键优化点

  • 缓存Introspection结果:在插件中添加缓存层(如Redis),缓存已验证Token的元数据,有效期设为Token的剩余过期时间,减少对Identity Server的重复调用。
  • HTTPS通信:确保KrakenD与Identity Server之间的请求使用HTTPS,避免凭证或Token泄露。
  • 错误处理:针对Introspection端点的超时、错误响应,直接返回401/403,避免无效请求流入后端服务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:13:22