需使用OpenResty(含ngx_lua模块),通过access_by_lua_block/file在location中执行鉴权逻辑,校验JWT、查Redis黑名单,并注意非阻塞调用、超时控制、pcall异常处理及共享字典缓存。

要在 Nginx 的 location 块中集成 Lua 脚本实现动态鉴权与访问控制,核心是使用 OpenResty(Nginx + Lua 运行时)提供的 ngx_lua 模块,通过 access_by_lua* 钩子在请求进入代理或静态服务前执行 Lua 逻辑。
确认环境已支持 Lua 脚本
原生 Nginx 不支持 Lua,必须使用 OpenResty 或编译时启用 ngx_http_lua_module。验证方式:
- 运行
nginx -V 2>&1 | grep -o with-http-lua-module,输出含该字符串表示已启用 - 若用 OpenResty,直接安装官方包即可,默认集成完整 Lua 支持
- 确保
lua_package_path和lua_package_cpath(如需加载第三方库)在http块中正确配置
在 location 中嵌入鉴权 Lua 逻辑
推荐使用 access_by_lua_block(内联脚本)或 access_by_lua_file(外部文件),避免阻塞式操作。示例:校验请求头中的 token 并查 Redis 验证有效性:
location /api/ {
# 加载共享字典(可选,用于缓存鉴权结果)
set $auth_cache_key "";
<pre class="brush:php;toolbar:false;">access_by_lua_block {
local jwt = require "resty.jwt"
local redis = require "resty.redis"
-- 1. 提取 Authorization 头
local auth_header = ngx.var.http_authorization
if not auth_header or not string.find(auth_header, "^Bearer ") then
ngx.status = 401
ngx.say('{"error":"Unauthorized"}')
ngx.exit(401)
end
local token = string.sub(auth_header, 8)
-- 2. 解析并校验 JWT(可选签名、过期等)
local jwt_obj = jwt:new()
local verified_token, err = jwt_obj:verify_jwt_obj(token, { secret = "your-secret-key" })
if not verified_token then
ngx.status = 401
ngx.say('{"error":"Invalid token"}')
ngx.exit(401)
end
-- 3. 查询 Redis 判断是否黑名单或权限不足
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "Redis connect error: ", err)
ngx.status = 500
ngx.exit(500)
end
local is_blocked, err = red:get("blacklist:" .. verified_token.payload.jti)
if is_blocked == "1" then
ngx.status = 403
ngx.say('{"error":"Forbidden"}')
ngx.exit(403)
end
-- 4. 可选:将用户信息注入后续变量供 upstream 使用
ngx.var.auth_user_id = verified_token.payload.user_id or "unknown"
}
proxy_pass http://backend;
proxy_set_header X-User-ID $auth_user_id;}
注意关键安全与性能细节
Lua 鉴权虽灵活,但易引入隐患,务必关注以下几点:
-
避免阻塞操作:禁止使用
os.execute、io.open等同步系统调用;Redis 必须用resty.redis的非阻塞接口 -
超时控制:所有外部依赖(Redis、HTTP 请求)必须设
set_timeout,并在失败时明确返回错误码,防止请求挂起 -
错误隔离:Lua 异常会触发 500,建议用
pcall包裹关键逻辑,统一处理异常分支 -
缓存优化:高频鉴权场景可配合
lua_shared_dict缓存校验结果(如 JWT payload),设置合理 TTL 减少重复解析
调试与日志辅助定位问题
开发阶段开启详细日志,快速发现 Lua 执行问题:
- 在
http块中设置:lua_log_level notice;(或debug,需编译时启用 debug 日志) - 用
ngx.log(ngx.INFO, "user:", ngx.var.auth_user_id)记录关键路径 - 检查
error.log中的 Lua 错误(如 “attempt to index a nil value”),常见于未判空的变量访问 - 使用
curl -I -H "Authorization: Bearer xxx" http://your-domain/api/验证状态码和响应头


















