ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Apache APISIX public-api 插件实战:把插件内置 API 安全地暴露为公共端点

Apache APISIX public-api 插件实战:把插件内置 API 安全地暴露为公共端点 Apache APISIX public-api 插件实战把插件内置 API 安全地暴露为公共端点【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisixpublic-api是 Apache APISIX 中的一个轻量级插件用于通过通用的 HTTP API 路由器把某个插件内置的 API 端点例如 jwt-auth 的/apisix/plugin/jwt/sign签名端点暴露给外部调用。本文结合插件源码与测试用例讲解 public-api 的配置属性、三种典型用法直接暴露、自定义 URI、叠加认证插件加固并梳理其收集插件 API → 构建专用路由 → 访问阶段二次匹配的底层实现链路帮助你安全、规范地开放插件能力。插件概述为什么需要 public-api在 APISIX 中很多插件内部实现了管理类/工具类的 HTTP API。例如 jwt-auth 插件提供了生成 JWT 令牌的接口/apisix/plugin/jwt/signwolf-rbac 提供了user_info查询接口prometheus、node-status、batch-requests、jwe-decrypt 等插件也都通过_M.api()导出了各自的 API。关键问题是这些插件内置的 API 默认并不会对外暴露。如果想要访问必须由用户手动创建一个 Route并在该 Route 上启用public-api插件。这正是 public-api 存在的意义——它充当桥梁把插件内部 API 注册到一条真实的网关路由上让请求得以按预期路由和处理。:::note 重要约定 插件内置的公共 API 默认不对外暴露用户必须手动配置 Route 并在其上启用public-api插件公共 API 才会生效。 :::工作原理解析从插件 API 到网关路由要真正用好 public-api理解它的底层实现非常关键。整个过程分为注册与匹配两个阶段。阶段一插件通过_M.api()注册 API以 jwt-auth 为例插件通过实现_M.api()方法声明自己提供的公共 APIfunction _M.api() return { { methods {GET}, uri /apisix/plugin/jwt/sign, handler gen_token, } } end这里声明了一个GET /apisix/plugin/jwt/sign端点其处理函数gen_tokenjwt-auth.lua会从请求参数中读取key消费方 key与可选的payload查找对应的 Consumer并调用对应的签名算法HS256/RS256/ES256 等生成 JWT 令牌返回。阶段二api_router统一收集并构建路由APISIX 在启动/热加载时会遍历所有已加载插件收集各插件_M.api()返回的路由构建一个独立的 API 路由器。这部分逻辑位于 apisix/api_router.lua遍历plugin_mod.plugins对每个实现了api字段的插件调用api_fun()获取其 API 路由列表将methods、paths即 uri、handler包装后插入路由表最终router.new(routes)生成基于 radixtree 的路由器该路由器通过core.lrucache.global(api_router, plugin_mod.load_times, fetch_api_router)全局缓存插件变更时自动重建。值得注意的是fetch_api_router还会统计是否存在非/apisix/前缀的 API 路由has_route_not_under_apisix这一信息会被其他模块如 admin API 的 token 校验逻辑用来决定是否需要对/apisix/路径做额外保护。阶段三public-api 在 access 阶段完成二次路由public-api 插件本身只有几十行代码核心逻辑全部集中在access阶段apisix/plugins/public-api.luafunction _M.access(conf, ctx) -- 若用户在配置中指定了目标 uri则覆盖请求的原始 uri ctx.var.uri conf.uri or ctx.var.uri -- 执行 API 路由匹配 if router.api.match(ctx) then return end return 404 end流程拆解改写 uri如果配置了uri属性就把ctx.var.uri改写为目标公共 API 的原始 URI例如/apisix/plugin/jwt/sign未配置时保持请求原本的 URI 不变。匹配插件 API调用router.api.match(ctx)apisix/api_router.lua用请求方法和改写后的 URI 在插件 API 路由器中dispatch命中则执行对应插件的handler并返回结果。兜底 404如果匹配不到任何插件 API直接返回404。插件声明priority 501public-api.lua意味着它在网关的访问阶段靠前执行能够在其他业务逻辑介入前完成 URI 改写与 API 分发。属性说明名称类型必填默认值描述uristring否公共 API 的 URI。配置 Route 时使用该属性指定插件内置公共 API 的原始 URI即插件_M.api()中声明的 uri。当uri为空/未配置时public-api 直接以 Route 自身配置的uri作为匹配目标要求该 uri 与插件声明的公共 API uri 一致例如/apisix/plugin/jwt/sign当uri有值时请求首先到达 Route 配置的对外 URI随后 public-api 会把请求改写转发到uri指向的插件 API实现对外别名效果。前置准备开始配置前请确保已正确安装并启动 APISIX默认 Admin API 端口为9180网关数据面端口为9080已为相关插件如 jwt-auth配置好 Consumer 与插件参数。本文示例沿用官方文档约定使用 jwt-auth 的key: user-key消费方jwt-auth 与 key-auth 的完整配置请参阅各自的插件文档jwt-auth、key-auth。实战用法一基础用法——直接暴露插件 API在 Router1上启用 public-api并让 Route 的uri直接指向 jwt-auth 插件的公共 API 地址curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/r1 \ -H X-API-KEY: api-key \ -H Content-Type: application/json \ -d { uri: /apisix/plugin/jwt/sign, plugins: { public-api: {} } }此时访问该 URI 即可获得 JWT 响应key参数对应前面配置的消费方 keycurl http://127.0.0.1:9080/apisix/plugin/jwt/sign?keyuser-key由于 Route 的uri与插件声明的公共 API uri 一致public-api 无需改写 URI 就能在 API 路由器中命中gen_tokenhandler返回签名后的 JWT。实战用法二自定义 URI——对外隐藏插件 API 路径很多场景下我们不希望把/apisix/plugin/...这种内部路径暴露给调用方此时可以利用 public-api 的uri属性做路径别名外部使用简洁的/gen_token内部改写为/apisix/plugin/jwt/sign。curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/r2 \ -H X-API-KEY: api-key \ -H Content-Type: application/json \ -d { uri: /gen_token, plugins: { public-api: { uri: /apisix/plugin/jwt/sign } } }现在调用方只需访问新端点curl http://127.0.0.1:9080/gen_token?keyuser-key注意如果uri指向的插件公共 API 不存在或者映射错误请求将返回404。测试用例 t/plugin/public-api.t 中的 TEST 5 与 TEST 6 专门验证了这一点——访问不存在的插件 API/apisix/plugin/balalbala、或把uri错误配置为不存在端点时均得到404。实战用法三安全加固——叠加认证插件保护公共 APIpublic-api插件本身不提供任何鉴权能力直接把内部 API尤其是令牌签发这类敏感接口暴露出来是存在风险的。官方推荐的做法是在同一个 Route 上叠加认证插件如 key-auth让公共 API 只对持有凭证的调用方开放。curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/r2 \ -H X-API-KEY: api-key \ -H Content-Type: application/json \ -d { uri: /gen_token, plugins: { public-api: { uri: /apisix/plugin/jwt/sign }, key-auth: {} } }带上了正确的apikey请求头后请求会被放行返回200 OKcurl -i http://127.0.0.1:9080/gen_token?keyuser-key \ -H apikey: test-apikeyHTTP/1.1 200 OK缺少认证信息时请求在 key-auth 阶段即被拦截返回401 Unauthorizedcurl -i http://127.0.0.1:9080/gen_token?keyuser-keyHTTP/1.1 401 Unauthorized这条认证插件 public-api的组合在测试 t/plugin/public-api.t 的 TEST 7TEST 9 中被完整覆盖配置 Consumerkey: testkey与 key-auth 后携带apikey: testkey的请求正常放行未携带时返回401。测试中还使用了serverless-pre-function输出日志来确认路由确实被命中进一步佐证了 public-api 的二次分发流程在 rewrite 阶段之后照常生效。移除插件删除配置即可生效如需移除 public-api 插件或重置 Route只需删除 Route 中plugins对应的配置即可APISIX 会自动热加载无需重启。官方文档同时提供了便捷地获取 Admin API 密钥的命令——从 conf/config.yaml 中提取admin_key并保存为环境变量需借助yq工具admin_key$(yq .deployment.admin.admin_key[0].key conf/config.yaml | sed s///g)随后即可用该密钥更新 Route例如将 Route 1 恢复为普通代理路由此时 public-api 已不在插件列表中插件 API 不再对外暴露curl http://127.0.0.1:9180/apisix/admin/routes/1 -H X-API-KEY: $admin_key -X PUT -d { uri: /hello, upstream: { type: roundrobin, nodes: { 127.0.0.1:1980: 1 } } }测试与验证从仓库测试理解行为边界仓库测试文件 t/plugin/public-api.t 覆盖了 public-api 的全部关键行为可作为排查问题的参考测试用例场景期望结果TEST 1schema 校验uri传数字校验失败报wrong type: expected string, got numberTEST 2创建三类 Route自定义 uri 映射、直接暴露、错误映射全部创建成功201TEST 3命中自定义 uri 映射的/gen_token返回合法的 HS256 JWTTEST 4直接暴露的 wolf-rbacuser_infoAPI路由命中有插件日志返回 401wolf-rbac 自身鉴权拦截TEST 5访问不存在的插件 API404TEST 6访问 uri 映射错误的公共 API404TEST 79key-auth 保护公共 API有apikey返回 200无则 401总结public-api 插件的核心价值在于以插件注册 API 网关二次路由的机制把原本只存在于插件内部的 HTTP 能力通过标准 Route 安全、可控地暴露给外部调用方。实际使用时记住三条原则默认不暴露插件公共 API 必须配合显式配置的 Route 与 public-api 插件才能对外可用路径即别名uri属性用于指定目标插件 API 的原始地址可以实现对外路径隐藏与重命名务必加固public-api 本身不做鉴权涉及令牌签发、用户信息等敏感接口时应叠加 key-auth、jwt-auth 等认证插件或通过其他网关策略IP 限制、限流等加以保护。【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表