我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

本文描述的nginxauth_request模块的一个简单的小用法,可以在一个现有的系统外部,凭空增加一层全局验证,并且对系统原有代码做到零侵入。这个方法可是听起来有点小厉害的。本文中,仅仅实现了改写部分,并没有实现具体的用户名密码验证逻辑。也就是说:本文仅仅实现了登录框的拦路,并没有实现用户名密码的验证的细节,光拦截了没有通过的细节部分。

苏南大叔:nginx的auth_request模块,如何改写401状态码默认行为? - nginx-auth-request
nginx的auth_request模块,如何改写401状态码默认行为?(图6-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验文章。本文测试环境:win10nginx@1.15.11php@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的配置,仅仅是为了更容易地说明本文的问题,而进行的配置最简化。实际的配置,会更加复杂。参考的原版配置,来自这里:

苏南大叔:nginx的auth_request模块,如何改写401状态码默认行为? - nginx-location-conf
nginx的auth_request模块,如何改写401状态码默认行为?(图6-2)

本文没有贴出auth这个站点的nginx配置,就是最简单的.php的配置,可以参考苏南大叔的其它文章。比如:

苏南大叔:nginx的auth_request模块,如何改写401状态码默认行为? - auth-php-conf
nginx的auth_request模块,如何改写401状态码默认行为?(图6-3)

auth/check.php

这里实际上应该完成cookie为基础的逻辑验证,但是这里并没有实现,因为这个不是本文的重点。这里的逻辑是:只要验证失败,就要发出401状态码。然后再由nginxerror_page 401进行转写。

重点就是401状态码的发出,就代表着验证不通过。

header('WWW-Authenticate: Basic realm="My Realm Name"');
header('HTTP/1.0 401 Unauthorized');

苏南大叔:nginx的auth_request模块,如何改写401状态码默认行为? - ldap-401
nginx的auth_request模块,如何改写401状态码默认行为?(图6-4)

nginx拦截401代码

nginx通过auth_request模块进行鉴权拦截,所以请确保auth_request模块已经被正确编译。可以通过下面的命令来进行确认。

nginx -V

正确的输出里面会有auth_request的字样。

苏南大叔:nginx的auth_request模块,如何改写401状态码默认行为? - nginx模块检测
nginx的auth_request模块,如何改写401状态码默认行为?(图6-5)

使用方式是:

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的auth_request模块,如何改写401状态码默认行为? - 改写登录框
nginx的auth_request模块,如何改写401状态码默认行为?(图6-6)

参考文章

实际效果就是如截图所示。如果没有强制的改写,则是浏览器跳出鉴权对话框。如果被强制代码转写后,就变成了普通可自定义的登录框。本文实际上参考了nginx官方的一个项目,地址如下:

原版的是用python完成的验证和表单逻辑,不过存在着一些小的问题,待后续讨论。

结束语

苏南大叔的更多nginx相关文章,请点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   nginx