access阶段

291 阅读4分钟

access阶段是用于控制请求是否可以继续向下访问。

一、access模块

access模块是一个很简单的模块,是用于控制哪些IP可以访问某些url,哪些ip不可以访问某些url。模块名是ngx_http_access_module,默认是被编译进nginx中的,可以使用--without-http_access_module进行禁用

access模块提供两条指令:

  • allow:允许哪些地址可以访问某些url。
  • deny:禁止哪些地址可以访问某些url。

这两条指令可以出现在http、location、server、limit_except上下文中。

设置deny之后,access阶段之前的阶段还是会被执行。

当一个location中配置了多条allow或者deny,例如:

location / {
    allow 1.1.1.1;
    deny 2.2.2.2;
    allow 3.3.3.3;
    .....
}

当匹配到第一条时,后面的就不会执行,如果没有匹配到第一条,则会向下匹配。

二、auth_basic模块

auth_basic模块是可以对用户名密码做限制,进行校验的模块。

auth_basic模块默认是编译进nginx中的(Openresty默认没有编译),可以使用--without-http_auth_basic_module进行禁用。

1、HTTP Basic Authentication

HTTP Basic Authentication鉴权的过程:

客户端访问nginx时,nginx会返回一个401响应,并且响应体中有一个WWW-Authenticate字段,浏览器在接收到该响应之后,就会弹出一个要求输入账号密码的弹出框,输入提交之后,浏览器就会讲我们输入的账号密码存在Credentials字段中,以明文的方式发送给nginx,所以这里传输数据很不安全,使用HTTPS加密之后就安全了。

2、auth_basic指令

auth_basic指令值为string或者off,默认为off。string即为弹出框的title。可以出现的上下文为http、location、server、limit_except。

3、auth_basic_user_file

该指令的值为一个文件地址,该文件是一个存储user:password的文件,可以存储多个。

三、auth_request模块

auth_request模块默认是没有被编译到nginx中的,需要使用--with-http_auth_request_module方法进行添加编译。

1、原理

当nginx接收到客户端请求之后,会生成一个子请求,并通过反向代理技术发送给上游服务器,上游服务器处理之后,返回响应。如果返回的状态码是2xx,则继续执行,如果是401或者403,则返回给客户端。

2、指令

  • auth_request:默认是关闭的,值可以为url,nginx会生成一个子请求,然后去匹配location模块。

  • auth_request_set:为变量设置值,使用:auth_request_set $val value

3、案例

本地启动两个nginx项目,一个是nginx-demo,一个是nginx-demo1。

nginx-demo的配置:

upstream local {
        server 127.0.0.1:3000;
    } 


    server {
        listen       8000;
        server_name localhost;
        server_name_in_redirect on;
       
        error_page 404 /50x.html;
        error_log logs/error.log info;
        
        location / {
           auth_request /test;
        }
        
        location = /test {
            proxy_pass http://local;
            proxy_pass_request_body off;
            proxy_set_header Content_Length '';
            
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

解释:当请求http://localhost:8000/时,nginx会产生一个字请求:http://localhost:8000/test,该子请求匹配到locaion = /test {....}模块,并代理到http://local,即nginx-demo1的nginx上。

nginx-demo1的配置:

    server {
        listen       127.0.0.1:3000;
        server_name  localhost;

        location /test {
           return 401 '401';
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

解释:nginx-demo1的nginx接收到来自nginx-demo的子请求,匹配到location /test模块,并返回401,nginx-demo在接收到该返回之后,将该子请求的结果发送给客户端,客户端显示结果如下:

如果nginx-demo1的location /test模块中return的为200,那么它会返回html/index.html文件,即使这里没有配置root和try_files。

四、satisfy指令

satisfy指令允许我们改变模块的执行顺序。

1、使用

satisfy指令的值只能是all或者any。上下文为http、server、location中。

access阶段有多个模块,当satisfy设置为all时,access阶段的所有模块都通过之后,才会向下执行,任何一个模块拒绝之后,就会返给客户端4xx或者5xx错误;当satisfy设置为deny时,access阶段的任意模块通过之后,就会向下执行。

五、一个access模块执行过程

执行过程:

  • 当执行access阶段时,先判断access模块的allow或者deny有没有设置。

  • 当allow或者deny都没有设置,则认为忽略该模块,继续向下执行下一个模块。

  • 当请求放行之后,判断satisfy指令的值,如果为any,则access阶段的任何一个模块通过,就向下执行下一个阶段。如果为all,则需要access阶段的所有模块都通过,才会向下执行下一个阶段。

  • 当请求被拒绝之后,判断satisfy指令的值,如果为any,则向下执行下一个模块,如果为all,则直接拒绝请求,不再向下执行。

六、问题

1、如果有return指令,access阶段还会执行吗?

答:不会,return指令存在server rewrite和rewrite阶段,在access之前,所以一旦执行return,就会向用户返回响应,不会再向下执行。