在网关层做JWT校验可统一鉴权、避免重复实现,OpenResty通过Lua脚本解析token、验签、检查有效期及黑名单,并透传用户信息至后端。

为什么在网关层做 JWT 校验
把用户身份校验放在网关层,能避免每个后端服务重复实现鉴权逻辑,统一拦截非法请求、提前拒绝未授权访问。Nginx 本身不支持解析 JWT,但通过 OpenResty(集成了 Lua 和大量 Lua 库的 Nginx 发行版),就能在 Nginx 配置中嵌入 Lua 脚本,完成 token 解析、签名验证、有效期检查、白名单/黑名单判断等关键操作。
环境准备与基础配置
确保已安装 OpenResty(非普通 Nginx),并启用 lua-resty-jwt 和 lua-resty-http 等常用库。推荐用 luarocks 安装:
luarocks install lua-resty-jwtluarocks install lua-resty-http
在 nginx.conf 的 http 块中添加 Lua 模块路径和共享字典(用于缓存公钥或黑名单):
lua_package_path "/path/to/lua/?.lua;;"; lua_shared_dict jwt_cache 10m;
核心 Lua 脚本:解析并校验 JWT
在 location 或 server 块中使用 access_by_lua_block 执行鉴权逻辑。典型流程包括:
- 从
Authorization请求头提取 Bearer token - 调用
jwt:load_jwt()解析 token 结构 - 用公钥(RSA)或密钥(HS256)验证签名有效性
- 检查
exp(过期时间)、nbf(生效时间)、iss(签发者)等标准字段 - 可选:查 Redis 黑名单判断是否被主动注销
示例片段(简化版):
access_by_lua_block {
local jwt = require "resty.jwt"
local jwt_obj = jwt:new()
local auth_header = ngx.req.get_headers()["Authorization"]
if not auth_header or not string.find(auth_header, "Bearer ") then
ngx.exit(401)
end
local token = string.sub(auth_header, 7)
local res, err = jwt_obj:verify_jwt_obj(token, { secret = "your-secret-key", algorithm = "HS256" })
if not res then
ngx.log(ngx.ERR, "JWT verify failed: ", err)
ngx.exit(401)
end
}
进阶:动态公钥加载与权限透传
生产环境多用 RSA 非对称签名,公钥需安全分发。可让 Lua 脚本从本地文件或远程服务(如 Keycloak JWK 端点)拉取并缓存公钥,利用 lua_shared_dict 减少重复请求。
校验成功后,常需将用户 ID、角色等信息透传给后端服务:
- 用
ngx.var设置自定义变量(如ngx.var.jwt_uid = res.payload.uid) - 在
proxy_set_header中转发:proxy_set_header X-User-ID $jwt_uid;
这样后端无需再解析 token,直接读取可信头部即可做细粒度 RBAC 控制。


















