在Nginx中实现API签名校验需使用OpenResty(集成Lua),通过access_by_lua_block在请求转发前校验X-Signature、X-Timestamp和X-Nonce,采用HMAC-SHA256+Base64算法比对签名,并用ngx.secure_compare防时序攻击。

要在 Nginx 中实现 API 接口的签名校验,核心是利用 OpenResty(Nginx + Lua)在请求进入后端前,通过 Lua 脚本验证请求签名是否合法。这能有效防止未授权调用、重放攻击和参数篡改。
安装支持 Lua 的 OpenResty
Nginx 官方版不内置 Lua 支持,必须使用 OpenResty 或编译 nginx-lua-module。推荐直接安装 OpenResty:
- Ubuntu/Debian:
sudo apt install -y software-properties-common && sudo add-apt-repository -y ppa:openresty/ppa && sudo apt update && sudo apt install -y openresty - CentOS/RHEL:
sudo yum install -y epel-release && sudo yum install -y openresty - 安装后,
openresty -v应显示版本,openresty -V可确认 lua-resty-core 等模块已加载
设计签名规则并前置校验逻辑
典型签名方式为:对请求方法、路径、时间戳、随机串、排序后的参数(或 body)拼接后,用密钥 HMAC-SHA256 加密,再 Base64 编码。示例规则:
- Header 传参:
X-Signature(签名值)、X-Timestamp(秒级时间戳,误差 ≤ 300 秒)、X-Nonce(一次性的随机字符串) - 签名原文 =
GET|/api/user?uid=123&ts=1717021234|abc123xyz(方法|路径+查询参数|nonce) - 服务端用相同算法 + 预置密钥重新计算签名,比对一致才放行
在 location 中嵌入 Lua 校验代码
在 Nginx 配置中,于目标 API 的 location 块内使用 access_by_lua_block 拦截请求:
location /api/ {
access_by_lua_block {
local core = require "resty.core"
local hmac = require "resty.hmac"
local json = require "cjson"
local ngx = ngx
<pre class="brush:php;toolbar:false;"> -- 配置密钥(生产环境建议从安全存储读取)
local SECRET_KEY = "your_api_secret_key"
-- 获取必要 header
local signature = ngx.req.get_headers()["X-Signature"]
local timestamp = tonumber(ngx.req.get_headers()["X-Timestamp"])
local nonce = ngx.req.get_headers()["X-Nonce"]
if not (signature and timestamp and nonce) then
ngx.exit(400)
end
-- 时间有效性检查(防重放)
local now = ngx.time()
if math.abs(now - timestamp) > 300 then
ngx.exit(401)
end
-- 构造待签名字符串:method|uri|args|nonce
local method = ngx.var.request_method
local uri = ngx.var.uri
local args = ngx.var.args or ""
local sign_str = string.format("%s|%s%s|%s", method, uri, args == "" and "" or "?" .. args, nonce)
-- 计算服务端签名
local calc_hmac = hmac:new(SECRET_KEY, "sha256")
calc_hmac:update(sign_str)
local expected = calc_hmac:final()
local expected_b64 = ngx.encode_base64(expected)
if not ngx.secure_compare(signature, expected_b64) then
ngx.exit(401)
end
}
proxy_pass http://backend;
proxy_set_header Host $host;
}
注意使用 ngx.secure_compare 防时序攻击,勿用 == 直接比较字符串。
可选增强:签名支持 JSON Body 和缓存 nonce
若接口接收 JSON 请求体,需在 access_by_lua_block 前启用 lua_need_request_body on;(仅开发期用,生产慎用),并解析 body:
- 用
ngx.req.read_body()+ngx.req.get_body_data()获取原始 body - 对 body 做标准化(如去空格、字段排序)后再参与签名计算
- 为防重放,可将
nonce + timestamp存入 shared_dict 或 Redis,校验后标记已用(需配合过期清理)
不复杂但容易忽略。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











