使用 OpenResty 在 Nginx 层通过 access_by_lua_block 拦截请求,计算并比对 HMAC 签名。适合内部 API 或公开 API 网关,风险在于密钥泄露和时钟不同步。
先说结论:Nginx Lua 适合网关层轻量鉴权,无需独立认证服务。
- 适合:高并发 API 网关或微服务入口
- 优先做:强制 HTTPS 传输防止密钥嗅探
- 再验证:日志中确认签名失败率与时间戳偏差
命令速用版
以下为 Nginx 配置核心片段,需安装在支持 Lua 的 OpenResty 环境:
location /api/ {
access_by_lua_block {
-- 此处调用签名验证脚本
require("resty.signature").verify()
}
proxy_pass http://backend;
}为什么会这样
Lua 脚本运行在 Nginx worker 进程内,避免了外部网络调用带来的延迟。
API 签名鉴权的核心是确认请求来源合法且未被篡改,Nginx Lua 模块允许在请求到达后端前完成哈希计算与比对,公开资料中没有看到可靠的量化数据表明具体延迟降低多少,但架构上减少了跳数。
分步处理
1. 环境准备:安装 OpenResty 确保包含 ngx_lua 模块。
2. 密钥管理:将 AppSecret 存储在 Nginx 变量或外部存储中,不要硬编码在脚本里。
3. 脚本编写:使用 lua-resty-hmac 或 openssl 库计算 HMAC-SHA256,参数需按字典序排序。
4. 配置加载:在 nginx.conf 的 http 块加载 lua_package_path,在 location 块调用验证逻辑。
怎么验证是否生效
使用 curl 发送带签名头的请求,观察 HTTP 状态码是否为 200。
查看 Nginx error.log,确认是否有签名验证失败的日志记录。
常见坑
1. 时间同步:客户端与服务端时间偏差超过容差会导致鉴权失败。
2. 参数排序:签名计算前必须对参数 key 进行字典序排序,否则哈希值不一致。
3. 明文传输:未启用 HTTPS 时,签名密钥可能在传输中被截获。
常见问题
时间偏差多大算正常?
通常建议容差设置在 5 分钟以内,具体取决于业务安全等级。
支持哪些签名算法?
常用 HMAC-SHA256,Lua 可通过 openssl 模块实现。
会影响 Nginx 性能吗?
Lua 代码在 VM 中运行,复杂逻辑会占用 CPU,建议保持脚本轻量。
参考来源
- OpenResty 官方文档,OpenResty® - Official Site,https://openresty.org/
- ngx_lua 模块文档,ngx_lua - Nginx Lua Module,https://github.com/openresty/lua-nginx-module