Nginx auth_request 模块使用笔记
📌 模块概述
nginx-auth-request-module
(官方名:http_auth_request_module
)用于在请求处理前向外部服务进行认证验证。
🔧 安装与启用
# 编译时添加模块
./configure --add-module=/path/to/nginx-auth-request-module# 检查是否已安装
nginx -V 2>&1 | grep -o http_auth_request_module
🎯 基础配置
server {listen 80;server_name example.com;location / {auth_request /auth; # 认证检查error_page 401 = @error401; # 认证失败处理proxy_pass http://backend; # 后端服务}location = /auth {internal; # 内部访问proxy_pass http://auth-service/validate;proxy_pass_request_body off;proxy_set_header Content-Length "";proxy_set_header X-Original-URI $request_uri;}location @error401 {return 302 /login?redirect=$request_uri;}
}
📊 认证服务要求
状态 | HTTP状态码 | 说明 |
---|---|---|
认证成功 | 200 | 允许访问 |
认证失败 | 401 | 未认证 |
认证失败 | 403 | 无权限 |
⚠️ 常见问题:JSON状态码处理
当认证服务返回JSON格式的状态码时(如 {"code": 401, "msg": "认证失败"}
),需要特殊处理:
方案1:修改认证服务(推荐✅)
// 认证服务直接返回正确的HTTP状态码
app.get('/validate', (req, res) => {if (!isAuthenticated(req)) {return res.status(401).json({ // 直接设置HTTP状态码code: 401,msg: "认证失败"});}res.status(200).json({ code: 200 });
});
方案2:使用Lua处理(需要OpenResty)
location = /auth {internal;proxy_pass http://auth-service/validate;proxy_pass_request_body off;proxy_set_header Content-Length "";header_filter_by_lua_block {local resp_body = ngx.var.upstream_resp_bodyif resp_body thenlocal cjson = require "cjson"local ok, data = pcall(cjson.decode, resp_body)if ok and data and data.code == 401 thenngx.status = 401 # 覆盖状态码endend}
}
🚀 高级功能
1. 传递用户信息
location / {auth_request /auth;auth_request_set $user $upstream_http_x_auth_user;auth_request_set $roles $upstream_http_x_auth_roles;proxy_set_header X-User $user;proxy_set_header X-Roles $roles;proxy_pass http://backend;
}
2. 认证缓存
http {auth_request_cache_zone shared:auth_cache 10m;server {location / {auth_request /auth;auth_request_cache shared:auth_cache;auth_request_cache_key "$cookie_sessionid";auth_request_cache_valid 200 5m;proxy_pass http://backend;}}
}
3. 完整头信息传递
location = /auth {internal;proxy_pass http://auth-service/validate;proxy_pass_request_body off;proxy_set_header Content-Length "";# 传递所有相关信息proxy_set_header X-Original-Method $request_method;proxy_set_header X-Original-URI $request_uri;proxy_set_header X-Original-IP $remote_addr;proxy_set_header Host $host;proxy_set_header Authorization $http_authorization;proxy_set_header Cookie $http_cookie;
}
🔍 调试技巧
# 添加调试头信息
add_header X-Auth-Status $upstream_status;
add_header X-Auth-User $user;
add_header X-Auth-Roles $roles;# 日志记录
log_format auth_log '$remote_addr - $user [$time_local] ''"$request" $status $body_bytes_sent ''"$http_referer" "$http_user_agent" ''auth_status:$upstream_status';access_log /var/log/nginx/auth.log auth_log;
🛡️ 安全考虑
-
超时设置:避免认证服务不可用导致阻塞
proxy_connect_timeout 3s; proxy_read_timeout 5s;
-
错误处理:认证服务宕机时的降级策略
location = /auth {proxy_next_upstream error timeout invalid_header;proxy_intercept_errors on;error_page 500 502 503 504 = @auth_service_down; }location @auth_service_down {# 允许访问或拒绝所有请求return 200; # 或 return 403; }
📋 最佳实践
- ✅ 认证服务直接返回HTTP状态码
- ✅ 使用HTTPS保护认证请求
- ✅ 设置合理的超时时间
- ✅ 实现认证服务的健康检查
- ✅ 记录详细的认证日志
- ❌ 避免在认证请求中传递敏感数据
🎪 应用场景
场景 | 配置特点 |
---|---|
JWT认证 | 传递Authorization头,验证token |
角色控制 | 基于返回的角色头信息进行权限判断 |
多因素认证 | 链式认证请求 |
API网关 | 统一认证所有后端服务 |
总结:优先让认证服务返回正确的HTTP状态码,如无法修改再考虑使用Lua/NJS处理JSON响应。合理配置缓存和超时以确保系统稳定性。