标题:【Nginx16】Nginx学习:访问认证及过滤器模块

文章目录
    分类:存储运维 标签:Nginx

    Nginx学习:访问认证及过滤器模块

    结束了 HTTP 核心模块的学习,我们就进入到了扩展模块,按文档顺序,我们先来了解的就是 访问限制 与 认证 相关的模块,此外,还有一个过滤模块。这几个模块还是非常有意思的,特别是过滤模块可以给返回的内容前后增加内容,非常像我们套模板时会分离出来的头尾模板一样。而认证类的则是 HTTP Basic 相关的内容,之前在学习 PHP 相关的小文章时也有过接触。总体来说,难度不大,赶紧玩起来吧。


    今天所有的配置指令都可以配置在 http、server、location 模块下,遵循向上查找原则。

    访问限制 Access 模块

    ngx_http_access_module 模块,这个模块的功能和命令参数和 Apache 中的基本一样。通常 Apache 的配置中都会写上访问限制,Nginx 其实这一块用得少,先来看看配置的效果。

    location /access/ {
      alias /usr/local/nginx/html/;
      allow 192.168.56.88;
      deny all;
    }

    192.168.56.88 是当前 Nginx 运行的虚拟机的 IP ,我的电脑主机的 IP 是 192.168.56.1 ,这个配置的意思是禁止所有的访问,但允许 192.168.56.88 的访问。


    直接从我的电脑主机访问 http://192.168.56.88/access/ ,直接返回 403 错误。而在虚拟机上使用 curl 访问,就可以正常返回结果。这就是访问限制的作用。


    访问限制也可以配置为 IPv6 地址,并且可以是 IP 段,也可以加上子网,比如官网给出的配置。

    location / {
        deny  192.168.1.1;
        allow 192.168.1.0/24;
        allow 10.1.1.0/16;
        allow 2001:0db8::/32;
        deny  all;
    }

    这一段的意思就是禁止所有的 IP 访问,允许 192.168.1.010.1.1.02001:0db8:: IP 段,但除了 192.168.1.1


    需要注意的是,它是按从上到下的顺序进行匹配的,有一个符合了就返回。比如说上面我们的配置中,把 allow 和 deny 换个位置的话,那么当匹配到 deny all 时,所有的请求都会被打回,不会走到 allow 了。其实就和 Apache 一样,deny all 这种配置,一定要放到最后。

    allow

    允许指定的网络地址访问。没有默认值。

    allow address | CIDR | all;

    deny

    拒绝指定的网络地址访问。没有默认值。

    deny address | CIDR | all;

    HTTP 认证 AuthBasic 模块

    还记得我们之前学习过的 PHP的HTTP验证 https://mp.weixin.qq.com/s/H8I1MSeqsuOn16lKXZ4Nrw 这篇文章嘛?时间有点久了,不记得了也没关系,可以去复习下哦。当时,我们是通过 PHP 来实现的 HTTP 基础验证。其实,如果是固定的目录,那么这套东西都不需要用使用到 PHP 这种动态语言来实现,直接 Nginx 这边处理掉就好啦。


    它的全名是 ngx_http_auth_basic_module 模块。要怎么配置呢?首先,我们需要生成一个 crpyt() 加密的密码,使用 openssl 命令就可以。

    [root@localhost nginx]# openssl passwd 123456
    5okRX5nWEJxew

    然后,创建一个密码文件,我就在 Nginx 编译时指定的 /etc/nginx/ 目录下新建一个 conf 目录,然后放在这里面。

    // /etc/nginx/conf
    [root@localhost conf]vim htpasswd
    zyblog:5okRX5nWEJxew

    好了,帐号密码准备好了,直接去 Nginx 配置一个就行了。

    location /authbasic/ {
      alias /usr/local/nginx/html/;
      auth_basic 'test';
      auth_basic_user_file conf/htpasswd;
    }

    一共就俩指令。一会再详细看它们的说明,先试试吧。


    直接访问的话,会发现马上就返回了 401 错误。如果是这样的话,那就证明咱们配置的没问题。如果你是使用浏览器请求,那么会弹出一个用户名和密码的输入框,直接输入就好了。而如果是 Postman 测试的话,直接使用 Authorization 选择 Basic Auth 填上用户名和密码就行了。请求之后会发现多了一个请求头,像下图这样。


    //img1.zyblog.com.cn/20230804/b9d569dd2bdf9e90cb6a1ae322934d9b.png


    之前学习的时候我们就说过,这个 Basic Auth 是不安全的,Base64 就是一个编码,直接就能解码。enlibG9nOjEyMzQ1Ng== 解码后正是 zyblog:123456


    接下来访问的话,会正常展示页面了。这就是整个 AuthBasic 模块配置的全部效果了,是不是非常简单方便。

    auth_basic

    auth_basic string | off;

    启使用“HTTP基本认证”协议的用户名密码验证。 指定的参数被用作 域 或者可以理解为就是起个名字。 参数 off 可以取消继承自上一个配置等级 auth_basic 指令的影响。


    这个配置项其实是有点意思的,如果是个字符串,表明开启 AuthBasic 功能,这个字符串我们可以自己定义,如果是 off ,就相当于关闭。


    假设在 server 模块中有个全局的 AuthBasic 配置,但我们想要某个访问 URI 不需要 AuthBasic 验证,就可以设置 auth_basic 为 off 。

    auth_basic 'all';
    auth_basic_user_file conf/htpasswd;
    location /noauthbasic/{
      alias /usr/local/nginx/html/;
      auth_basic off;
    }

    这样,访问其它所有的页面路径时,都需要验证,但是只有 noauthbasic 相关的路径时,是不需要验证的。

    auth_basic_user_file

    指定保存用户名和密码的文件。

    auth_basic_user_file file;

    没有默认值,文件就是一个文本文件。可以给相对路径,也可以给绝对路径。文件路径可以使用变量,文件内容的格式就是 name:password 这样的键值对。需要注意的就是密码是需要加密的。


    另外,可以使用多个用户名和密码,每行代表一个用户。

    Request 验证模块

    Request 验证模块是 1.5.4 版本之后所支持的。这个验证是什么意思呢?其实就是我们访问某个路径的时候,通过向另外一个 URI 发送一个请求,通过这个 URI 返回的结果来断定是否有权限,比如说子请求返回 200 系列的状态码,就表示有权限可以正常访问。而 401 或者 403 则会直接返回相应的无权限结果。除此之外的响应,都会返回 500 错误。


    这个模块是需要单独添加编译的,在 configure 时添加 --with-http_auth_request_module 参数就可以使用了。一般它会配合 ngx_http_access_module、ngx_http_auth_basic_module、ngx_http_auth_jwt_module 以及在 HTTP 核心配置中学习过的 satisfy 配置指令来使用。访问限制的顺序是 acces、auth、auth_request,如果 satisfy 设置为 all ,则必须所有验证都通过,而如果设置 any 的话,只要有一个通过,后续就不会再进行限制了。


    不过咱们学习的话,就简单的让子请求返回状态码就好啦。

    location /authrequest1/ {
      alias /usr/local/nginx/html/;
      auth_request /authrequest/ok/;
    }
    
    location /authrequest2/ {
      alias /usr/local/nginx/html/;
      auth_request /authrequest/err/;
    }
    
    location /authrequest/ok/ {
       return 200;
    }
    location /authrequest/err/ {
       return 403;
    }

    访问 /authrequest1/ 和 /authrequest2/ 分别会发送子请求到 /authrequest/ok/ 和 /authrequest/err/ ,这两个子请求一个返回 200 ,一个返回 403 ,相应地,/authrequest1/ 会正常返回页面,而 /authrequest2/ 则会显示 403 的错误页面。你也可以试试返回其它的状态码,看看会有什么效果。


    请求验证可以帮助我们实现对资源的统一权限验证,这在微服务中非常有用,我们可以实现自己的权限认证服务,将所有的资源的请求都通过权限认证服务后再进行处理,提高了系统的安全性。但同时会增加请求的响应时间,因为此时每次请求都会发起两次http调用。好吧,说实话,这一段抄来的,但是确实说得没毛病,虽说我对微服务也是一知半解吧,但是感觉说得对。如果有有相关经验的小伙伴欢迎留言评论哦!

    auth_request

    基于子请求的结果启用授权,并设置子请求将发送到的URI。

    auth_request uri | off;

    默认值是 off ,开启就是直接设置一个 URI 就好了。

    auth_request_set

    在授权请求完成后,将请求变量设置为给定值。

    auth_request_set $variable value;

    没有默认值,它的值可以包含来自授权请求的变量,比如 $upstream_http_* 之类的。不过上面我没有测试,因为我也不知道咋测试。

    过滤器 Addition 模块

    这个过滤器模块听着名称很高大上吧?其实它就是可以针对响应内容,在响应内容的前后增加文本的一种过滤器。这里的文本指的其实是一个子请求返回的响应内容,也就是说,像上面的请求验证一样,它会发送一个子请求,但是这回不要状态码了,只要返回的响应内容。这个模块也是不直接包含在核心的 Nginx 基础源码中的,需要 configure 添加 --with-http_addition_module 进行编译安装。


    先来看看效果吧。

    location /additionbefore/ {
    	alias /usr/local/nginx/html/;
    }
    location /additionafter/ {
    	return 200 after;
    }
    
    location /addition/ {
      alias /usr/local/nginx/html/;
      add_before_body /additionbefore/aaa.html;
      add_after_body /additionafter/;
    }
    
    

    首先我们定义了两个路径,分别是 /additionbefore/ 表示在响应内容之前添加的文本和 /additionafter/ 表示在响应内容之后添加的文本。并且使用两种形式,一个是指定了目录别名,一会我们会用到指定目录下的文件,而另一个则是直接 return 回的文本。


    接下来,在 /addition/ 中,分别使用 add_before_body 添加响应内容之前要添加的文本,使用 add_after_body 添加响应内容之后要添加的文本。


    试试看吧,正常我们应该返回的 index.html 的内容中,前面多了 aaa.html 的内容,后面也多出了一段 after 字符。很有意思吧。给我个人的感觉,就像文章开头所说的,它非常像我们在套页面模板时,分出的 header.html 和 footer.html 这种东西。

    add_before_body

    add_before_body uri;

    在响应正文之前加入一段文字,nginx会发起一个子请求去获取这些文字。

    add_after_body

    add_after_body uri;

    在响应正文之后加入一段文字,nginx会发起一个子请求去获取这些文字。

    addition_types

    指定生效的响应MIME类型,默认始终包含“text/html”。

    addition_types mime-type ...;

    它的默认值就是 text/html ,而且不管你设置什么值,它始终也会包含 text/html 。


    这个配置是啥意思呢?我们前面的代码中没有演示。其实呀,它的意思就是,在默认情况下,只有 text/html 这种类型的响应可以使用 add_before_body 和 add_after_body 。比如下面这个配置,我们强制返回的响应 MIME 类型必须为 application/json 。types 相关的指令才刚学完没多久,大家没忘吧。

    location /addition/json/ {
      types {}
      default_type application/json;
      add_before_body /additionbefore/aaa.html;
      add_after_body /additionafter/;
      #addition_types application/json;
      return 200 '[]';
    }

    如果不打开注释的内容,你会发现返回的结果是不会有前后添加的内容的。而打开注释,就会有前后添加的内容了。addition_types 的作用就在这里。

    总结

    说实话,今天学习的这些配置,平常真的用得不多。不过幸好在之前很多的学习中就接触过这些概念,所以理解起来也并不困难。一般来说,如果说我们线上的数据库必须要能够在外网访问,并且可以随时访问的话,可能大家都会考虑上个 phpMyAdmin 。而我则喜欢在 phpMyAdmin 的访问 location 上再加上一个 Basic Auth 验证。虽说可能作用不大,而且还是明文传输的吧,但是再配合上 https ,安全性还是略有保障的,至少不至于裸着就能被人访问到。


    另外,在 Nginx 的商业版 1.11.3 版本之后还有 JWT 验证模块。不过商业版就不在我们的讨论范围内了,如果确实有 JWT 验证的需求,可以考虑 OpenResty 相关的实现。这个大家可以自己查阅下相关的资料哦,毕竟到目前为止,我也还没打算学 OpenResty 呢。


    参考文档:


    http://nginx.org/en/docs/http/ngx_http_access_module.html


    http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html


    http://nginx.org/en/docs/http/ngx_http_auth_request_module.html


    http://nginx.org/en/docs/http/ngx_http_addition_module.html

    视频链接

    微信文章地址:https://mp.weixin.qq.com/s/50ri-xjr7ctMSrp9PqxdyQ

    B站视频地址:https://www.bilibili.com/video/BV1Kj411x7EL

    搜索
    关注