假设我们起了一个服务器在 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抽风的时候要有耐心)。
