假设我们起了一个服务器在 1234 端口,但是我暴露在公网上,但是又需要被授权的人方便的使用,一般情况下我们会在程序里简单加一个密码验证,或者直接使用 Auth_Basic
设置一个用户名与密码。Nginx Auth_Basic 扫描是恶意爬虫最喜欢干的事,而限制 Auth_Basic 重试次数又需要配置 Fail2ban 之类的日志监控程序,很麻烦。
在应用层设置密码对大多数开发人员来说并没有什么难点,但是有时候我们搭建的系统并不是自己开发的,甚至是已经编译好的庞然大物,就有些困难了。
这里分享一个10分钟快速搭建 OAuth2.0 授权登录系统的方法,本文使用 github 作为示例。
实现的原理是通过nginx的 auth_request 模块检测授权,如果没有授权,返回401错误,nginx将授权请求发送给授权系统,这里使用的是vouch-proxy,如果已经授权,则正常充当反向代理。
多数新版 nginx 的发行版中都已经默认包含了auth_request模块,你可以通过nginx -V
命令查看编译参数中是否包含了--with-http_auth_request_module
,如果没有可以选择升级 nginx 到最新版或者重新编译 nginx,详情本文不再赘述。
GitHub 配置
首先登录GitHub,建立一个OAuth app,callback URL 填写域名/auth
提交之后你会得到应用的 Client ID
与 Client Secret
。
Vouch 配置
把这段命令中的client_id
和client_secret
修改成上一步获取的值。
配置中provider
设置的是GitHub,也可以是 Google、AWS Cognito等其他的或自定义库,请多详情可以参考项目主页。
# 建立Vouch配置目录 mkdir -P /var/lib/vouch/config/ mkdir -P /var/lib/vouch/data/ # 建立配置文件 echo '# Vouch config vouch: listen: 0.0.0.0 port: 9090 # 授权域名列表 domains: - xiumu.org # 允许访问的GitHub ID列表 whiteList: - ixiumu oauth: provider: github client_id:client_secret: ' > /var/lib/vouch/config/config.yml # 拉起vouch服务器 docker run -d -p 9090:9090 --name vouch-proxy -v /var/lib/vouch/config:/config -v /var/lib/vouch/data:/data voucher/vouch-proxy
Nginx 配置
生产环境请配置 SSL 证书开启 HTTPS,粘贴下面的配置到http
段,或者在目录/etc/nginx/conf.d
新建文件
upstream vouch { server 127.0.0.1:9090; } server { listen 80; #listen 443 ssl http2; server_name _; #ssl_certificate /etc/nginx/____.crt; #ssl_certificate_key /etc/nginx/____.key; location = /validate { # cache validate # proxy_cache_valid 200 30s; # proxy_cache auth_cache; # proxy_cache_methods GET; # proxy_cache_key $cookie_vouchcookie; # forward the /validate request to Vouch Proxy proxy_pass http://vouch; # be sure to pass the original host header proxy_set_header Host $http_host; # Vouch Proxy only acts on the request headers proxy_pass_request_body off; proxy_set_header Content-Length ""; # optionally add X-Vouch-User as returned by Vouch Proxy along with the request auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user; # optionally add X-Vouch-IdP-Claims-* custom claims you are tracking # auth_request_set $auth_resp_x_vouch_idp_claims_groups $upstream_http_x_vouch_idp_claims_groups; # auth_request_set $auth_resp_x_vouch_idp_claims_given_name $upstream_http_x_vouch_idp_claims_given_name; # optinally add X-Vouch-IdP-AccessToken or X-Vouch-IdP-IdToken # auth_request_set $auth_resp_x_vouch_idp_accesstoken $upstream_http_x_vouch_idp_accesstoken; # auth_request_set $auth_resp_x_vouch_idp_idtoken $upstream_http_x_vouch_idp_idtoken; # these return values are used by the @error401 call auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt; auth_request_set $auth_resp_err $upstream_http_x_vouch_err; auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount; } location /login { # forward the /login request to Vouch Proxy proxy_pass http://vouch; # be sure to pass the original host header proxy_set_header Host $http_host; } location /auth { # forward the /auth request to Vouch Proxy proxy_pass http://vouch; # be sure to pass the original host header proxy_set_header Host $http_host; } # if validate returns `401 not authorized` then forward the request to the error401block error_page 401 = @error401; location @error401 { # redirect to Vouch Proxy for login return 302 $scheme://$http_host/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err; } # real server location / { # send all requests to the `/validate` endpoint for authorization auth_request /validate; proxy_redirect off; proxy_http_version 1.1; proxy_pass http://127.0.0.1:1234; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Accept-Encoding gzip; } }
重启 Nginx 服务,现在访问网址会跳转到 GitHub 请求授权,之后再访问的时候就会直接连续跳转两次进入应用,几乎感知不到(GitHub抽风的时候要有耐心)。