Nginx实现API Token认证:如何将redis2_query结果存入变量?
解决Nginx+Redis API认证中Redis结果直接返回导致proxy_pass失效的问题
我来帮你搞定这个问题!你当前的配置里,redis2_pass会直接把Redis的查询结果返回给客户端,这就导致proxy_pass完全没机会执行——毕竟请求已经被Redis的响应终结了。要实现"先验证Token存在性,再转发API请求"的逻辑,我们可以用Nginx的**auth_request模块**,它专门用来处理这种前置认证的场景,完美适配你的需求。
实现思路
核心逻辑是把Redis Token验证放到一个内部专用的location里,这个location只负责返回认证的状态码(200表示通过,403表示拒绝),不会把Redis的实际查询内容返回给客户端。然后在你的API location里,通过auth_request调用这个内部认证接口,只有认证通过时,才会继续执行proxy_pass转发到后端服务。
具体配置示例
1. 配置内部认证location(处理Redis查询)
这个location只能被Nginx内部调用,不能直接被外部请求访问:
location = /auth-token { internal; # 标记为内部location,禁止外部直接访问 set $token $http_securitytoken; # 先检查请求头里有没有SecurityToken if ($token = "") { return 403; } # 向Redis发起查询请求 redis2_query get $token; redis2_pass 127.0.0.1:6379; # 处理Redis的响应,只返回状态码 redis2_response_header off; body_filter_by_lua_block { local resp_body = ngx.arg[1] # 如果Redis返回空(Token不存在),返回403;否则返回200 if not resp_body or resp_body == "" then ngx.status = 403 ngx.arg[1] = nil # 清空响应体,只返回状态码 else ngx.status = 200 ngx.arg[1] = nil end } }
2. 配置API的主location(转发请求)
在你的API路径下,添加auth_request指令来触发认证:
location /api/ { # 触发内部认证请求 auth_request /auth-token; # 可选:把认证的状态码保存到变量,方便后续日志或处理 auth_request_set $auth_status $upstream_status; # 认证通过后,转发到后端API服务 proxy_pass http://127.0.0.1:9003; # 按需添加必要的代理头 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
关键说明
auth_request模块:从Nginx 1.5.4版本开始支持,大部分主流发行版的Nginx默认都编译了这个模块,如果你的版本太旧可能需要重新编译。- Lua过滤器:这里用
body_filter_by_lua_block来处理Redis的响应,需要Nginx集成了Lua模块(比如OpenResty默认包含,或者自行编译ngx_http_lua_module)。如果没有Lua模块,也可以通过匹配Redis响应的特征来判断,但Lua的方式更灵活直观。 - Redis响应处理:我们只关心Redis返回的内容是否为空——空表示Token不存在,返回403;非空表示Token有效,返回200,同时清空响应体,避免多余内容返回给客户端。
测试验证
- 确保Redis里存在一个测试Token,比如执行
set test_token "valid" - 发起请求时带上
SecurityToken: test_token头,应该能正常访问后端API - 不带Token或者带无效Token时,应该直接返回403状态码
内容的提问来源于stack exchange,提问作者Ankit Bansal
相关产品推荐
相关产品推荐

