背景
现在有两个系统,一个是管理系统,一个是文件系统,需要实现通过管理系统对文件系统的访问的鉴权
分析
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
默认的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(无权限)的区别了 _
有疑问加站长微信联系(非本文作者)