美文网首页
API接口统一认证

API接口统一认证

作者: 码氪丝 | 来源:发表于2019-11-16 13:00 被阅读0次

    需求

    • 云服务器环境中有多组内网服务器,提供基于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

    相关文章

      网友评论

          本文标题:API接口统一认证

          本文链接:https://www.haomeiwen.com/subject/yxfyictx.html