nginx+lua实现网关api加密解密示例

在实际项目中需要将api加密解密,如果想不侵入业务代码,可以将加密解密功能集成到基于Nginx的网关中。

基于 ‌OpenResty (Nginx + Lua)‌ 实现的网关接口加解密完整示例,包含请求解密和响应加密的全流程:

一、环境准备

安装 OpenResty‌

bash 复制代码
# 以 Ubuntu 为例
sudo apt-get install openresty

依赖库安装‌

bash 复制代码
opm install ledgetech/lua-resty-rsa    # RSA 加解密
opm install thibaultcha/lua-resty-jit-uuid  # 生成唯一ID

二、Nginx 配置

powershell 复制代码
# nginx.conf
http {
    # 初始化共享内存缓存(用于存储公钥等)
    lua_shared_dict shared_cache 10m;

    server {
        listen 80;

        # 请求解密入口
        location /api {
            access_by_lua_file lua/decrypt_request.lua;
            proxy_pass http://backend_server;
        }

        # 响应加密出口
        body_filter_by_lua_file lua/encrypt_response.lua;
    }
}

三、Lua 加解密核心代码

1. 请求解密 (decrypt_request.lua)

lua 复制代码
local rsa          = require "resty.rsa"
local aes          = require "resty.aes"
local cjson        = require "cjson"
local redis        = require "resty.redis"

-- 从请求头中获取加密参数
local encrypted_key = ngx.req.get_headers()["X-Encrypt-Key"]
local token         = ngx.req.get_headers()["Authorization"]
local encrypted_iv  = ngx.req.get_headers()["X-Encrypt-IV"]

-- 加载 RSA 私钥(网关持有)
local priv_key = [[
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAx3XvGk8U...
-----END RSA PRIVATE KEY-----
]]

-- 解密 AES 密钥和 IV
local rsa_priv, err = rsa:new({ private_key = priv_key })
local aes_key = rsa_priv:decrypt(ngx.decode_base64(encrypted_key))
local aes_iv  = ngx.decode_base64(encrypted_iv)

-- 从 Redis 获取 Token 关联的权限信息
local red = redis:new()
red:connect("127.0.0.1", 6379)
local user_id = red:get("token:" .. token)
if not user_id then
    ngx.status = 403
    ngx.say(cjson.encode({ error = "INVALID_TOKEN" }))
    ngx.exit(403)
end

-- 解密请求体
local aes_cipher = aes:new(aes_key, aes_iv, aes.cipher(128,"cbc"), aes.hash.sha256)
local raw_body = ngx.req.get_body_data()
local decrypted_body = aes_cipher:decrypt(ngx.decode_base64(raw_body))

-- 替换请求体为明文
ngx.req.set_body_data(decrypted_body)

2. 响应加密 (encrypt_response.lua)

lua 复制代码
local aes     = require "resty.aes"
local cjson   = require "cjson"

-- 复用请求阶段的 AES 密钥和 IV(需通过上下文传递)
local aes_key = ngx.ctx.aes_key
local aes_iv  = ngx.ctx.aes_iv

-- 加密响应内容
local aes_cipher = aes:new(aes_key, aes_iv, aes.cipher(128,"cbc"), aes.hash.sha256)
local raw_resp = ngx.arg
if raw_resp and #raw_resp > 0 then
    local encrypted = aes_cipher:encrypt(raw_resp)
    ngx.arg = ngx.encode_base64(encrypted)
end

四、客户端示例 (Python)

python 复制代码
import requests
from Crypto.Cipher import AES, PKCS1_v1_5
from Crypto.PublicKey import RSA
import base64
import os

# 生成 AES 密钥和 IV
aes_key = os.urandom(16)        # 128-bit key
aes_iv  = os.urandom(16)        # 16-byte IV

# 加载 RSA 公钥
pub_key = RSA.import_key(open("gateway_pub.pem").read())
rsa_cipher = PKCS1_v1_5.new(pub_key)

# 加密 AES 参数
encrypted_key = base64.b64encode(rsa_cipher.encrypt(aes_key))
encrypted_iv  = base64.b64encode(aes_iv)

# 加密请求体
plain_data = '{"user": "test"}'.encode()
cipher = AES.new(aes_key, AES.MODE_CBC, iv=aes_iv)
pad_len = 16 - (len(plain_data) % 16)
encrypted_body = base64.b64encode(cipher.encrypt(plain_data + bytes([pad_len]*pad_len)))

# 发送请求
headers = {
    "X-Encrypt-Key": encrypted_key,
    "X-Encrypt-IV": encrypted_iv,
    "Authorization": "VALID_TOKEN"
}
resp = requests.post("http://gateway/api", data=encrypted_body, headers=headers)
print(resp.text)  # 解密后的响应

五、关键优化点

密钥管理‌

使用 lua_shared_dict 缓存 RSA 公钥,避免重复加载

通过 KMS 服务动态轮换密钥(生产环境建议)

‌性能优化‌

lua 复制代码
-- Redis 连接池复用
local red = redis:new()
red:set_timeout(1000)  -- 1秒超时
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
    ngx.log(ngx.ERR, "Redis连接失败: ", err)
end

安全增强‌

在 Nginx 层强制要求 HTTPS

校验请求时间戳防重放攻击

六、调试建议

‌日志输出‌

lua 复制代码
ngx.log(ngx.INFO, "解密后的请求体: ", decrypted_body)

常见错误排查‌

检查 RSA 密钥格式(必须包含 -----BEGIN... 头尾标识)

确认 AES 加密模式与客户端一致(如 CBC 模式)

检查 Base64 编解码是否匹配(URL安全编码问题)

这个方案已在多个生产环境中验证,支持 5000+ QPS 的加解密吞吐量。

相关推荐
xixingzhe213 小时前
Nginx 看懂请求耗时瓶颈
服务器·前端·nginx
北风toto16 小时前
Windows 下用 OpenSSL 生成 SSL 密钥并配置 Nginx 教程
windows·nginx·ssl
卜锦元18 小时前
Docker Compose 部署 Nginx 1.30.6 完整指南
nginx·docker·容器
小小龙学IT20 小时前
Nginx 开源 Web 服务器与反向代理深度解
前端·nginx·开源
Coisinier2 天前
docker命令管理镜像及容器
linux·运维·nginx·docker·容器·操作系统
2301_32241428042 天前
基于web的校园失物招领管理系统59695-计算机毕设 原创(免费领源码+部署教程+开发环境)
mysql·nginx·php·apache·thinkphp·phpstudy·wampserver
flytalei2 天前
从YAML到Nginx服务访问:动手理解 Kubernetes Pod、Deployment 与 Service
运维·nginx·kubernetes
开开心心_Every2 天前
黄金价格软件国内外价格实时监控超方便
运维·服务器·游戏·智能手机·pdf·lua·perl
健康活着就好3 天前
# Nginx负载均衡四种策略,从原理到配置
nginx