需求
- 云服务器环境中有多组内网服务器,提供基于RESTFul的微服务;
- 外网通过Nginx反向代理分发到内网微服务中;
- 原始设计每个微服务独立验证JWT请求,现在需要在Nginx上进行统一认证,进而提高开发效率;
环境
CentOS 6.10
Nginx 1.16.1
最终方案
- 系统中不鉴别API参数
配置如下:
upstream auth_server {
server 192.168.1.250:80;
}
upstream login_server {
server 192.168.1.10:80;
}
server {
listen 80;
server_name ~^(?<subdomain>.+).jdzchao.com$;
proxy_set_header Host $host;
proxy_set_header Referer $http_referer;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /
{
auth_request /auth;
error_page 401 = @error401;
error_page 403 = @error403;
if ($subdomain = 'auth'){
return 501;
}
# return 505;
}
location /login
{
return 403;
}
location = /auth
{
internal;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Original-HOST $host;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-METHOD $request_method;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass http://auth_server/auth/;
}
location @error401
{
add_header Set-Cookie "NSREDIRECT=$scheme://$http_host$request_uri;Path=/";
return 302 http://login_server/;
}
location @error403
{
return 405;
}
}
踩坑方案一: 使用Nginx的Auth_request Module
通过注册auth_server,并开发一个API管理服务。
配置文件:
upstream auth_server {
server 192.168.1.250:80;
}
upstream login_server {
server 192.168.1.10:80;
}
server {
listen 80;
server_name ~^(?<subdomain>.+).jdzchao.com$;
proxy_set_header Host $host;
proxy_set_header Referer $http_referer;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /
{
auth_request /auth;
error_page 401 = @error401;
error_page 403 = @error403;
if ($subdomain = 'auth'){
return 501;
}
# return 505;
}
location /login
{
return 403;
}
location = /auth
{
internal; # 内网可访问
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Original-HOST $host;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-METHOD $request_method;
proxy_pass http://auth_server/auth/;
}
location @error401
{
add_header Set-Cookie "NSREDIRECT=$scheme://$http_host$request_uri;Path=/";
return 302 http://login_server/;
}
location @error403
{
return 405;
}
}
测试结果:
使用APIPOST进行测试,发送post数据到api.jdzchao.com域名的接口,结果如下:
- 直接获取的host为 auth_server,不是api.jdzchao.com
- 只能通过header获取一些转发的信息
- 请求超时,无响应
更改配置:
# 添加
location = /auth
{
internal; # 内网可访问
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Original-HOST $host;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-METHOD $request_method;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_pass http://auth_server/auth/;
}
测试结果:
- 无法获取post和get参数
更改配置:
proxy_pass_request_body on;
proxy_no_cache "1";
测试结果:
仍超时无法获取post和get参数
结论
原因是auth子请求是通过HTTP GET方法发送的,而不是POST.由于GET没有body,body被丢弃
现有模块的唯一解决方法是从请求正文中提取所需信息,并将其放入传递给auth服务的HTTP标头中.
参考文章:
http://nginx.org/en/docs/http/ngx_http_auth_request_module.html
https://www.cnblogs.com/vipzhou/p/8420808.html
https://codeday.me/bug/20190516/1114665.html
网友评论