nginx的auth_request模块,如何改写401状态码默认行为?
发布于 作者:苏南大叔 来源:程序如此灵动~本文描述的nginx
的auth_request
模块的一个简单的小用法,可以在一个现有的系统外部,凭空增加一层全局验证,并且对系统原有代码做到零侵入。这个方法可是听起来有点小厉害的。本文中,仅仅实现了改写部分,并没有实现具体的用户名密码验证逻辑。也就是说:本文仅仅实现了登录框的拦路,并没有实现用户名密码的验证的细节,光拦截了没有通过的细节部分。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验文章。本文测试环境:win10
,nginx@1.15.11
,php@8.2.1
。
nginx
配置
# upstream backend {
# server 127.0.0.1:9001;
# }
server {
server_name ldap;
listen 80;
location / {
auth_request /check;
error_page 401 =200 /login;
# auth_request http://auth/check.php; # 500 error
# proxy_pass http://backend/;
}
location = /check {
internal;
proxy_pass http://auth/check.php;
}
location /login {
proxy_pass http://auth/login.php;
}
}
这个nginx
的配置,仅仅是为了更容易地说明本文的问题,而进行的配置最简化。实际的配置,会更加复杂。参考的原版配置,来自这里:
本文没有贴出auth
这个站点的nginx
配置,就是最简单的.php
的配置,可以参考苏南大叔的其它文章。比如:
auth/check.php
这里实际上应该完成cookie
为基础的逻辑验证,但是这里并没有实现,因为这个不是本文的重点。这里的逻辑是:只要验证失败,就要发出401
状态码。然后再由nginx
的error_page 401
进行转写。
重点就是401
状态码的发出,就代表着验证不通过。
header('WWW-Authenticate: Basic realm="My Realm Name"');
header('HTTP/1.0 401 Unauthorized');
nginx拦截401代码
nginx
通过auth_request
模块进行鉴权拦截,所以请确保auth_request
模块已经被正确编译。可以通过下面的命令来进行确认。
nginx -V
正确的输出里面会有auth_request
的字样。
使用方式是:
location / {
auth_request /check;
error_page 401 =200 /login;
proxy_pass http://backend/;
}
上面的代码就是说,本来全部请求都要转向proxy_pass http://backend/
的,但是这里加入了一个auth_request /check
权限检测。/check
呢实际上也是个代理的页面,如果它验证不通过就会发出401
状态码。这个时候,就会被error_page 401
所拦截。强制把鉴权方式改成传统的表单模式。
backend
这个是个upstream
的设置,这并不在本文的讨论范围之内。
auth/login.php
这个逻辑就是非常简单,就放了一个传统的表单。
<form action="/login" method="post">
<table>
<tr><td>Username1: <input type="text" name="username"/></td></tr>
<tr><td>Password2: <input type="password" name="password"/></td></tr>
<tr><td><input type="submit" value="Login"></td></tr>
</table>
<input type="hidden" name="target" value="TARGET">
</form>
参考文章
实际效果就是如截图所示。如果没有强制的改写,则是浏览器跳出鉴权对话框。如果被强制代码转写后,就变成了普通可自定义的登录框。本文实际上参考了nginx
官方的一个项目,地址如下:
原版的是用python
完成的验证和表单逻辑,不过存在着一些小的问题,待后续讨论。
结束语
苏南大叔的更多nginx
相关文章,请点击:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。