Nginx层通过OpenResty的Lua模块实现Cookie签名验证,利用HMAC-SHA256绑定uid、role、ts等字段并校验sig,确保完整性、真实性和防重放(15分钟有效期),配合HttpOnly/Secure等安全设置,轻量高效且无状态。

直接在 Nginx 层对 Cookie 做签名验证,是轻量、高效且无状态的防篡改方案。OpenResty(Nginx + Lua)天然适合这类逻辑——不依赖后端,不引入数据库或 Redis,所有校验在入口层完成。
为什么用 Cookie 签名而不是明文存储
明文 Cookie(如 user_id=123; role=admin)极易被用户手动修改,导致越权或伪造身份。签名机制通过服务端密钥生成不可逆的校验值,绑定原始内容,确保:
- Cookie 内容未被篡改(完整性)
- Cookie 确实由本服务签发(真实性)
- 可选加入时间戳,限制有效期(防重放)
核心实现:用 lua-resty-cookie + HMAC-SHA256
OpenResty 推荐使用 lua-resty-cookie 解析 Cookie,并用 resty.sha256_hmac 或 openssl.hmac 计算签名。典型流程如下:
- 服务端写 Cookie 时:将关键字段(如
uid、role、ts)拼成字符串,用密钥计算 HMAC-SHA256,附加为签名字段(如sig),一起 Set-Cookie - 客户端请求时:Nginx 的
access_by_lua_block提取 Cookie,重新拼接字段并计算签名,比对请求中的sig - 不匹配或过期(
ts超出 15 分钟)则直接返回 401 或跳转登录页
配置示例(nginx.conf 片段)
在 server 块中添加:
location /api/ {
access_by_lua_block {
local cookie = require "resty.cookie"
local hmac = require "resty.sha256_hmac"
local secret = "your_32byte_secret_key_here" -- 生产环境建议从 env 或 config.lua 加载
<pre class="brush:php;toolbar:false;"> local c, err = cookie:new()
if not c then
ngx.exit(500)
end
local uid, err = c:get("uid")
local role, err = c:get("role")
local ts, err = c:get("ts")
local sig, err = c:get("sig")
if not (uid and role and ts and sig) then
ngx.exit(401)
end
local now = ngx.time()
if tonumber(ts) + 900 <p>}</p>安全增强建议
仅签名还不够,还需配合以下实践提升鲁棒性:
- Cookie 必须设置
HttpOnly和Secure(HTTPS 环境下),防止 XSS 窃取 - 签名密钥严禁硬编码在配置中;推荐通过
init_by_lua_block从环境变量或加密配置中心加载 - 避免在 Cookie 中存放敏感字段(如密码、token),只放必要标识,权限检查仍需后端二次校验
- 可结合
encrypted_session模块(需自行编译 Nginx)做 AES 加密 + HMAC 签名,进一步防泄露
这套机制不复杂但容易忽略细节,关键是签名字符串构造规则要前后端严格一致,且密钥生命周期管理到位。











