ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Nginx auth_request 模块使用

Nginx auth_request 模块使用

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;

🛡️ 安全考虑

  1. 超时设置:避免认证服务不可用导致阻塞

    proxy_connect_timeout 3s;
    proxy_read_timeout 5s;
    
  2. 错误处理:认证服务宕机时的降级策略

    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;
    }
    

📋 最佳实践

  1. ✅ 认证服务直接返回HTTP状态码
  2. ✅ 使用HTTPS保护认证请求
  3. ✅ 设置合理的超时时间
  4. ✅ 实现认证服务的健康检查
  5. ✅ 记录详细的认证日志
  6. ❌ 避免在认证请求中传递敏感数据

🎪 应用场景

场景 配置特点
JWT认证 传递Authorization头,验证token
角色控制 基于返回的角色头信息进行权限判断
多因素认证 链式认证请求
API网关 统一认证所有后端服务

总结:优先让认证服务返回正确的HTTP状态码,如无法修改再考虑使用Lua/NJS处理JSON响应。合理配置缓存和超时以确保系统稳定性。

返回列表