nginx跨域auth_request

钱tao · · 625 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

背景

现在有两个系统,一个是管理系统,一个是文件系统,需要实现通过管理系统对文件系统的访问的鉴权

分析

nginx 自带的auth_request可以实现该功能

方案和问题说明

server
    {    
        listen   8998 ssl;    # ssl后端
        ssl_certificate /etc/nginx/Sha2Crt.crt;
        ssl_certificate_key /etc/nginx/Sha2Crt.key; 
        client_max_body_size 20M; # 上传文件大小限制
        access_log /web/logs/filer_access.log;
        error_log /web/logs/filer_error.log;
        location / {
            auth_request /auth-proxy;

            # 传递403原因-后端配合
            auth_request_set $reason $upstream_http_reason;       
            add_header X-Reason $reason always;    
            add_header Access-Control-Expose-Headers X-Reason always;
            
             # Access-Control-Allow-Credentials 必须指定 Access-Control-Allow-Origin 而不能为*
            add_header Access-Control-Allow-Origin "$http_origin" always;
            add_header Access-Control-Allow-Credentials 'true' always;  # 将客户端的cookie转发给鉴权服务端
            add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT' always;
            add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,token' always;

            if ($request_method = 'OPTIONS') {
                return 204;
            }
            proxy_pass http://backend/;
        }

        location ^~ /seaweedfsstatic/ {
            proxy_pass http://backend/seaweedfsstatic/;
        }

        location = /auth-proxy {
            internal;

            proxy_pass https://mananger.example.com;  # 鉴权地址
            proxy_set_header X-Original-URI $request_uri;  # 给鉴权服务器带上访问的uri,判断路径权限使用
            proxy_set_header X-Request-Method $request_method; #请求的方法名
            proxy_pass_request_body off;            # 不转发body给鉴权
            proxy_set_header Content-Length "";     # 不转发body给鉴权
            expires 30s; 
        }
    }

问题总结:

1. add_header 问题http://nginx.org/en/docs/http/ngx_http_headers_module.html
image.png

默认的add_header只能在截图中指定的响应中生效,但是鉴权失败时我们使用的返回是403,为了能将鉴权的结果返还给客户端,每个add_header都需要添加always.

2. 跨域问题:

最初我使用 add_header Access-Control-Allow-Origin "$http_origin" ; 但是鉴权失败时返回403导致客户端收不到Access-Control-Allow-Origin头,客户端直接报跨域异常。 加上always解决。

3.鉴权后端改进

在golang的后端使用403返回并且将失败原因写入响应的头部

    if username == nil {
        logs.Error("username is nil, reject. ")
        c.Ctx.Output.Header("reason", "username is nil")
        c.CustomAbort(403, "username is nil, reject:"+Aisessionid)
        return
    }

再通过配置

            # 传递403原因-后端配合
            auth_request_set $reason $upstream_http_reason;       
            add_header X-Reason $reason always;    
            add_header Access-Control-Expose-Headers X-Reason always;

传递给客户端,客户端终于可以显示失败原因了。

其他

这样改造以后,客户端就能显示404(目录不存在、资源不存在)和403(无权限)的区别了 _


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:钱tao

查看原文:nginx跨域auth_request

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

625 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传