- config: 反向代理、缓存、负载均衡、安全、SSL 等配置模板 - lua: API 网关、认证、动态路由、限流、WebSocket 等脚本示例 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
134 lines
4.1 KiB
Plaintext
134 lines
4.1 KiB
Plaintext
# ============================================================
|
|
# Nginx access_by_lua 认证配置示例
|
|
# ============================================================
|
|
#
|
|
# 功能说明:
|
|
# - 使用 Lua 实现访问控制
|
|
# - JWT 验证
|
|
# - 自定义认证逻辑
|
|
#
|
|
# Lolly 对应配置:
|
|
# 可通过 Lua 沙箱实现自定义认证中间件
|
|
# ============================================================
|
|
|
|
http {
|
|
lua_shared_dict tokens 10m;
|
|
|
|
server {
|
|
listen 80;
|
|
server_name auth-lua.example.com;
|
|
|
|
# JWT 认证
|
|
location /api {
|
|
access_by_lua_block {
|
|
local jwt = require "resty.jwt"
|
|
|
|
-- 获取 Authorization 头
|
|
local auth_header = ngx.var.http_authorization
|
|
if not auth_header then
|
|
ngx.status = 401
|
|
ngx.header["WWW-Authenticate"] = 'Bearer realm="API"'
|
|
ngx.say('{"error": "Missing authorization header"}')
|
|
ngx.exit(401)
|
|
end
|
|
|
|
-- 解析 Bearer token
|
|
local _, _, token = string.find(auth_header, "Bearer%s+(.+)")
|
|
if not token then
|
|
ngx.status = 401
|
|
ngx.say('{"error": "Invalid token format"}')
|
|
ngx.exit(401)
|
|
end
|
|
|
|
-- 验证 JWT
|
|
local jwt_obj = jwt:verify("secret-key", token)
|
|
if not jwt_obj.verified then
|
|
ngx.status = 401
|
|
ngx.say('{"error": "Invalid token"}')
|
|
ngx.exit(401)
|
|
end
|
|
|
|
-- 将用户信息传递给后端
|
|
ngx.req.set_header("X-User-ID", jwt_obj.payload.sub)
|
|
ngx.req.set_header("X-User-Role", jwt_obj.payload.role)
|
|
}
|
|
|
|
proxy_pass http://backend:8080;
|
|
}
|
|
|
|
# API Key 认证
|
|
location /api/v2 {
|
|
access_by_lua_block {
|
|
local api_key = ngx.var.http_x_api_key
|
|
if not api_key then
|
|
ngx.status = 401
|
|
ngx.say('{"error": "Missing API key"}')
|
|
ngx.exit(401)
|
|
end
|
|
|
|
-- 从共享字典验证 API key
|
|
local tokens = ngx.shared.tokens
|
|
local user_id = tokens:get(api_key)
|
|
|
|
if not user_id then
|
|
ngx.status = 401
|
|
ngx.say('{"error": "Invalid API key"}')
|
|
ngx.exit(401)
|
|
end
|
|
|
|
ngx.req.set_header("X-User-ID", user_id)
|
|
}
|
|
|
|
proxy_pass http://backend:8080;
|
|
}
|
|
|
|
# IP 白名单 + Token 认证
|
|
location /admin {
|
|
access_by_lua_block {
|
|
local ip = ngx.var.remote_addr
|
|
|
|
-- IP 白名单检查
|
|
local whitelist = {
|
|
["127.0.0.1"] = true,
|
|
["10.0.0.0/8"] = true, -- 需要额外处理 CIDR
|
|
}
|
|
|
|
if not whitelist[ip] then
|
|
-- 非 IP 白名单,需要 Token
|
|
local token = ngx.var.http_x_admin_token
|
|
if not token or token ~= "admin-secret" then
|
|
ngx.status = 403
|
|
ngx.say('{"error": "Access denied"}')
|
|
ngx.exit(403)
|
|
end
|
|
end
|
|
}
|
|
|
|
proxy_pass http://admin-backend:8080;
|
|
}
|
|
}
|
|
}
|
|
|
|
# access_by_lua 说明:
|
|
#
|
|
# 1. 执行时机:
|
|
# - 在 rewrite 阶段之后
|
|
# - 在 content 阶段之前
|
|
# - 可用于访问控制
|
|
#
|
|
# 2. 常用操作:
|
|
# - ngx.exit(status): 终止请求,返回状态码
|
|
# - ngx.say(body): 输出响应体
|
|
# - ngx.req.set_header(): 设置请求头
|
|
# - ngx.req.get_headers(): 获取请求头
|
|
#
|
|
# 3. 认证模式:
|
|
# - JWT: 解析验证 JWT token
|
|
# - API Key: 从共享字典验证
|
|
# - Basic Auth: 自定义验证逻辑
|
|
# - OAuth: 调用外部服务验证
|
|
#
|
|
# 4. 性能优化:
|
|
# - 使用共享字典缓存验证结果
|
|
# - 避免每次请求都访问外部服务
|
|
# - 使用 cosocket 异步调用 |