尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

微服务认证与授权:07 — Kong(网关 / PEP)

微服务认证与授权:07 — Kong(网关 / PEP)
📅 发布时间:2026/7/7 17:49:18

07 — Kong(网关 / PEP)

📦 GitHub: https://github.com/geekchow/micro-service-auth

Kong 是 API 网关,也是策略执行点(PEP):它拦截每个请求、用Keycloak校验令牌、向OPA请求授权决策,并把被允许的请求转发给banking-api-service。

什么是 Kong

在本 PoC 所用的 IdP / PEP / PDP 分工中:

  • Keycloak是IdP—— 它签发令牌。
  • Kong是PEP—— 它在边缘执行访问控制。
  • OPA是PDP—— 它判定某个请求是否被允许。
  • banking-api-service是资源服务器—— 它拥有受保护的银行数据。

Kong 在本项目中的职责:

  1. 接收传入的 API 请求。
  2. 拒绝缺失或格式错误的Authorization头的请求。
  3. 调用Keycloak内省,确认令牌当前处于 active。
  4. 从令牌载荷中解码 JWT 声明。
  5. 用请求路径、方法与声明构建一个 input 对象。
  6. 调用OPA获取授权决策。
  7. 若OPA拒绝则返回403,若OPA允许则转发给banking-api-service。

Kong 不是身份提供方、不是策略引擎、也不是银行业务服务。

两个与 Kong 相关的配置文件

本仓库中有两个文件控制 Kong:

文件用途
docker-compose.yml容器串联 —— 镜像、端口、环境变量、卷、依赖
infra/kong/kong.ymlKong 运行时行为 —— service、route、plugin、plugin 配置值

它们之间的关系

docker-compose.yml

Kong container

infra/kong/kong.yml

infra/kong/plugins/opa-authz

banking-api-service

Keycloak

OPA

  • docker-compose.yml创建 Kong 容器并把配置挂载进去。
  • kong.yml告诉 Kong 要暴露什么路由、运行什么插件。
  • schema.lua定义哪些插件配置字段是合法的。
  • handler.lua包含每个请求都会运行的执行逻辑。

docker-compose.yml中的 Kong

相关的 Kong service 块:

kong:image:kong:3.7environment:KONG_DATABASE:offKONG_DECLARATIVE_CONFIG:/etc/kong/kong.ymlKONG_PLUGINS:bundled,opa-authzKONG_PROXY_ACCESS_LOG:/dev/stdoutKONG_ADMIN_ACCESS_LOG:/dev/stdoutKONG_PROXY_ERROR_LOG:/dev/stderrKONG_ADMIN_ERROR_LOG:/dev/stderrKONG_ADMIN_LISTEN:0.0.0.0:8001ports:-"8000:8000"-"8001:8001"depends_on:banking-api-service:condition:service_startedrestart:trueopa:condition:service_startedvolumes:-./infra/kong/kong.yml:/etc/kong/kong.yml:ro-./infra/kong/plugins/opa-authz:/usr/local/share/lua/5.1/kong/plugins/opa-authz:ro

关键环境变量:

  • KONG_DATABASE=off—— Kong 以无数据库(DB-less)模式运行。所有配置来自文件,而非数据库。
  • KONG_DECLARATIVE_CONFIG=/etc/kong/kong.yml—— 保存 Kong 声明式路由配置的文件。
  • KONG_PLUGINS=bundled,opa-authz—— 启用 Kong 内置插件以及自定义的opa-authz插件。
  • KONG_ADMIN_LISTEN=0.0.0.0:8001—— 在容器内暴露 Kong admin API。

关键卷:

  • kong.yml以只读方式挂载到容器内的/etc/kong/kong.yml。
  • 自定义插件目录以只读方式挂载到/usr/local/share/lua/5.1/kong/plugins/opa-authz—— 这是 Kong 扫描的标准 Lua 插件路径。

depends_on意味着 Kong 仅在banking-api-service与opa启动之后才启动。若banking-api-service重启,Kong 也会重启(restart: true)。

infra/kong/kong.yml中的 Kong

该文件使用 Kong 的声明式格式(_format_version: "3.0"),并定义了一个 service,内联一个 route 与一个 plugin:

_format_version:"3.0"services:-name:banking-apiurl:http://banking-api-service:8080routes:-name:banking-api-routepaths:-/api/accountsstrip_path:falseplugins:-name:opa-authzconfig:opa_url:http://opa:8181/v1/data/banking_authz/allowintrospection_url:http://keycloak:8080/realms/banking-poc/protocol/openid-connect/token/introspectintrospection_client_id:kong-introspectionintrospection_client_secret:kong-introspection-secrettimeout_ms:2000

Service

  • name: banking-api—— Kong 对上游的内部名称。
  • url: http://banking-api-service:8080—— Kong 把被允许的请求转发到这里。

Route

  • paths: [/api/accounts]—— 以/api/accounts开头的请求匹配此路由。
  • strip_path: false—— 路径按原样转发。

因此一个GET /api/accounts/A-1001的请求(来自alice或ops-admin)会按GET /api/accounts/A-1001转发到上游。

插件挂载与配置值

opa-authz插件在每个匹配该路由的请求上运行。它的配置提供了插件在运行时使用的实际 URL 与凭据:

  • opa_url—— Kong 把授权 input POST 过去的 OPA 端点。
  • introspection_url—— Kong 调用来检查令牌活跃性的Keycloak端点。
  • introspection_client_id—— 在Keycloak中注册的kong-introspectionclient。
  • introspection_client_secret—— 该 client 配对的密钥。
  • timeout_ms: 2000—— Kong 在中止前等待Keycloak或OPA的时长。

opa-authz插件

自定义插件位于infra/kong/plugins/opa-authz/,由两个文件组成:

schema.lua—— 配置定义

schema.lua声明了合法插件配置的形态。Kong 在启动时会用此 schema 校验任何opa-authz插件块:

return{name="opa-authz",fields={{config={type="record",fields={{opa_url={type="string",required=true}},{introspection_url={type="string",required=true}},{introspection_client_id={type="string",required=true}},{introspection_client_secret={type="string",required=true}},{timeout_ms={type="number",default=2000}},},},},},}
  • 四个 URL/凭据字段都是必填字符串 —— 任一缺失,Kong 都会拒绝启动。
  • timeout_ms是可选的,默认2000。
  • schema.lua定义什么是被允许的;kong.yml提供实际值;handler.lua在运行时使用它们。

handler.lua—— 执行逻辑

handler.lua在 Kong 的access阶段(优先级900)对每个匹配的请求运行。逻辑按以下顺序执行:

第 1 步 —— 读取 bearer 令牌

localauth_header=kong.request.get_header("authorization")ifnotauth_headerthenreturnkong.response.exit(401,{message="missing bearer token"})endlocaltoken=auth_header:match("[Bb]earer%s+(.+)")ifnottokenthenreturnkong.response.exit(401,{message="invalid bearer token"})end

若不存在Authorization头、或其中不含 bearer 令牌,则返回401。

第 2 步 —— 用Keycloak内省令牌

localintrospection,introspection_err=introspect_token(conf,token)ifnotintrospectionthenreturnkong.response.exit(503,{message="introspection unavailable",detail=introspection_err})endifintrospection.active~=truethenreturnkong.response.exit(401,{message="inactive token"})end

Kong 用introspection_client_id与introspection_client_secret以 HTTP Basic 认证,把令牌 POST 到Keycloak的内省端点。若Keycloak不可达,Kong 返回503。若令牌不是 active,Kong 返回401。

关于 Kong 为何使用内省而非基于 JWKS 的本地校验,见下文「为什么 Kong 使用内省而非 JWKS」。关于内省机制上如何工作,见 11 — JWT 签名、校验与内省。

第 3 步 —— 解码 JWT 声明

localclaims=decode_claims(token)ifnotclaimsthenreturnkong.response.exit(401,{message="unreadable jwt payload"})end

Kong 对 JWT 载荷段做 base64 解码并 JSON 解析以读取声明。这是一次本地解码 —— 没有额外的网络调用。

第 4 步 —— 确定有效角色

localfunctioneffective_role(claims)localrealm_access=claimsandclaims.realm_accesslocalroles=realm_accessandrealm_access.rolesor{}for_,roleinipairs(roles)doifrole=="ops-admin"thenreturn"ops-admin"endendfor_,roleinipairs(roles)doifrole=="customer"thenreturn"customer"endendreturnnilend

ops-admin优先于customer。若两个角色都不存在,effective_role返回nil。

第 5 步 —— 构建 OPA input 并调用OPA

localaccount_id=kong.request.get_path():match("/api/accounts/([^/]+)")localrequest_body=cjson.encode({input={method=kong.request.get_method(),path=kong.request.get_path(),account_id=account_id,customer_id=claim_value(claims.customer_id),account_ids=claim_values(claims.account_ids),role=effective_role(claims),username=claims.preferred_username,},})

对于像alice调用GET /api/accounts/A-1001这样的请求,Kong 从路径中提取account_id = "A-1001",并把它与其他字段打包成一个 JSON input 文档。

第 6 步 —— 执行OPA决策

ifdecision.result~=truethenreturnkong.response.exit(403,{message="forbidden"})end

OPA返回{"result": true}或{"result": false}。Kong 检查decision.result—— 任何非true(包括false或字段缺失)都会导致403。若OPA不可达或返回非 200 状态,Kong 返回503。

Kong 的请求流程

banking-api-serviceOPA (PDP)Keycloak (IdP)Kong (PEP)Client (alice / ops-admin)banking-api-serviceOPA (PDP)Keycloak (IdP)Kong (PEP)Client (alice / ops-admin)alt[deny][allow]alt[inactive][active]GET /api/accounts/A-1001 + Bearer tokenMatch /api/accounts routePOST introspect token{ "active": true } or { "active": false }401 inactive tokenDecode JWT claimsPOST { input: { method, path, account_id, customer_id, account_ids, role, username } }{ "result": true } or { "result": false }403 forbiddenForward GET /api/accounts/A-1001banking responsebanking response

与其他组件的互操作

Kong 与banking-api-service

Kong 只转发那些同时通过了Keycloak内省与OPA授权的请求。banking-api-service不直接对外暴露 —— 来自alice或ops-admin的所有流量都经由 Kong 到达。

banking-api-service也会用 JWKS 自行校验 JWT。这是纵深防御:银行服务不会因为 Kong 已经检查过就完全信任。

Kong 与identity-bootstrap-service

Kong 并不位于identity-bootstrap-service之前。bootstrap 是一个内部演示工具,位于同一 Compose 网络上,但 Kong 不向它路由任何流量。

Kong 与Keycloak

Kong 使用Keycloak做令牌内省,而不是把它当作自身管理访问的身份提供方。

为什么 Kong 使用内省而非 JWKS

Kong 是边缘 PEP。在它用令牌声明构建 OPA input 之前,它需要从Keycloak得到一个实时确认:该令牌此刻仍然处于 active。

一个令牌可能:

  • 仍然能被正确解码为 JWT,
  • 仍然带有有效的密码学签名,
  • 仍然处在其exp过期窗口内,

但Keycloak可能因为登出、会话过期或吊销,已经认为它 inactive。

基于 JWKS 的本地校验能确认签名、签发者、受众与过期 —— 但它无法反映Keycloak当前的会话状态。

内省让 Kong 在决定调用 OPA 之前,直接从Keycloak得到「真相之源」的答案。

因此设计是:

  • Kong 内省—— 在 OPA 之前、在边缘做实时令牌活跃性检查。
  • banking-api-serviceJWKS 校验—— 在资源服务器内部做快速的本地密码学校验。

关于内省如何工作的完整机制(HTTP 交互、Keycloak 的响应、active的含义),见 11 — JWT 签名、校验与内省。

Kong 与OPA

Kong 仅在令牌被确认 active 之后才调用OPA。OPA接收到:

字段来源
method请求的 HTTP 方法
path请求路径
account_id从/api/accounts/{account_id}提取
customer_idJWT 声明
account_idsJWT 声明(列表)
role推导得到:ops-admin|customer|nil
usernameJWT 的preferred_username声明

OPA返回{"result": true}或{"result": false}。Kong 据此执行。

把策略放在OPA里,意味着授权规则可以在不修改 Kong 或银行服务的情况下变更。

实用检查命令

从 Compose 网络内部发起请求时,使用辅助容器:

dockercomposeexeccurlsh

检查Keycloak的 OIDC discovery:

dockercomposeexeccurlcurlhttp://keycloak:8080/realms/banking-poc/.well-known/openid-configuration

检查OPA的策略端点:

dockercomposeexeccurlcurlhttp://opa:8181/v1/data/banking_authz/allow

检查banking-api-service健康状态:

dockercomposeexeccurlcurlhttp://banking-api-service:8080/actuator/health

从宿主机检查 Kong:

# Admin API — shows loaded routes, services, pluginscurlhttp://localhost:8001# Proxy — test the protected route (expect 401 without a token)curl-ihttp://localhost:8000/api/accounts/A-1001

← Prev: 06 — Keycloak / IdP · Next: 08 — OPA →


📚 返回专栏目录

相关新闻

  • Vue3 环境搭建 + 第一个 HelloVue 项目(零基础入门)
  • 终极指南:15分钟搞定黑苹果EFI配置,OpCore Simplify让复杂技术变得简单
  • 3步实现Windows经典游戏兼容性修复的终极指南

最新新闻

  • 状压dp-基础题目1(糖果)
  • 2026图片抠图边缘残留解决全指南,多工具精细处理实操方法
  • 让经典游戏在现代Windows上重获新生:dxwrapper的魔法指南
  • ppt模板_0146_客户服务
  • 【金蝶云星空】直运采购(无库存)全流程讲解
  • 龍魂资本愛之审计协议 CLAP v1.0 启动宣言

日新闻

  • Android逆向分析全能助手:集成化工具链与自动化工作流设计
  • 面搜索(Faceted Search)原理与工程实践指南
  • 神经网络调参避坑指南:从5个常见Loss曲线形态定位超参数问题

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号