HAProxy JWT验证:动态密钥/多密钥及JWKS支持问题咨询
解决HAProxy中JWT动态密钥/多密钥校验的方案
1. 多密钥校验的临时文件方案
虽然jwt_verify不支持动态变量作为密钥文件参数,但可以通过提前加载所有有效公钥文件,用or逻辑串联多个校验规则,只要任一密钥校验通过就允许请求:
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,/usr/local/etc/haproxy/kid1.pub) -m int 1 or http_auth_bearer,jwt_verify(txn.alg,/usr/local/etc/haproxy/kid2.pub) -m int 1 or http_auth_bearer,jwt_verify(txn.alg,/usr/local/etc/haproxy/kid3.pub) -m int 1 }
- 配合你的定时任务,密钥轮换时将新公钥写入对应文件,同时保留过渡期内的旧密钥文件,HAProxy会自动检测文件变化(无需重启)。
- 缺点是密钥数量较多时配置会冗长,但能满足过渡期多密钥共存的需求。
2. 动态密钥选择的Lua脚本方案
HAProxy支持Lua扩展,可通过脚本解析JWT头部的kid,动态匹配对应公钥校验:
步骤1:编写Lua脚本(jwt_dynamic_verify.lua)
local jwt = require("jwt") local cjson = require("cjson") function dynamic_jwt_verify(txn) -- 提取Bearer Token local auth_header = txn.sf:req_hdr("Authorization") if not auth_header or not auth_header:find("Bearer ") then return false end local token = auth_header:sub(8) -- 解析JWT头部获取kid local header_part = token:sub(1, token:find(".") - 1) local decoded_header = jwt.decode_base64(header_part) if not decoded_header then return false end local header = cjson.decode(decoded_header) local kid = header.kid if not kid then return false end -- 读取对应公钥文件并校验 local pub_key_path = "/usr/local/etc/haproxy/" .. kid .. ".pub" local pub_key_file = io.open(pub_key_path, "r") if not pub_key_file then return false end local pub_key = pub_key_file:read("*a") pub_key_file:close() return jwt.verify(token, pub_key, {alg = header.alg}) end
步骤2:在HAProxy配置中加载并调用脚本
global lua-load /usr/local/etc/haproxy/jwt_dynamic_verify.lua frontend your_frontend http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { lua.dynamic_jwt_verify }
- 优势:完全根据JWT的
kid动态匹配公钥,密钥轮换时无需修改HAProxy主配置。 - 注意:需确保HAProxy编译时启用Lua支持(
--with-lua),并安装jwt、cjsonLua库。
3. JWKS URL支持说明
截至HAProxy 2.8版本,原生不支持直接通过JWKS URL获取公钥。可通过以下方式间接实现:
- 用定时任务定期拉取JWKS,解析后按
kid保存为单个公钥文件,配合上述Lua脚本方案动态选择。 - 扩展Lua脚本,让脚本直接从JWKS URL拉取并缓存公钥(需处理缓存过期和多密钥共存逻辑),无需依赖本地文件。
内容的提问来源于stack exchange,提问作者Jens Popp
相关产品推荐
相关产品推荐

