- 【充电】《Nginx核心知识100讲》 access 阶段:i
- 【充电】《Nginx核心知识100讲》 preaccess阶段
- 【充电】《Nginx核心知识100讲》precontent阶段:
- 【充电】《Nginx核心知识100讲》postread阶段:获取
- 【充电】《Nginx核心知识100讲》content阶段:sta
- 【充电】《Nginx核心知识100讲》content阶段:ind
- 【充电】《Nginx核心知识100讲》nginx模块
- 【充电】《Nginx核心知识100讲》 rewrite阶段的re
- 【充电】《Nginx核心知识100讲》 rewrite阶段的re
- 【充电】《Nginx核心知识100讲》Log阶段:index模块
极客专栏《Nginx核心知识100讲》57~60小节,笔记
注意这个是看专栏视频,敲的哈。这个专栏让我收货蛮大的。
57 | access阶段:对ip做限制的access模块
image.png这个模块可以控制,哪些ip可以控制哪些url或者不可以访问。access阶段就是用来控制请求是否可以继续向下访问。access模块是这一阶段的第一个模块。
ngx_http_access_module
介绍
image.png默认是编译到nginx中的。进入access阶段前不生效,虽然deny了某些地址,对某些ip做限制了。limit_conn、limit_req照样生效。
语法
image.pnglocation里面是顺序执行的。当满足了一条之后,剩余的不在执行了。
留言问题
1.顺带这里想通了一件事,一般封ip用于内部吧,不用于对外。因为Nginx获取到的其实是用户的公网IP,而获取不到更细节那个用户的实际IP,所以一般对外不直接封IP,那样会误伤,因为那个局域网下其他用户也被限制了。
作者回复
实际情况中也要封IP的,比如针对爬虫时。
2.前两节limi-conn模块和limit-req模块中,他们是用到了共享内存,但这作用范围是全部work进程什么含义呢?
作者回复
含义是:如果你限制一个客户端最多1个连接,但nginx上配了2个worker进程,那么即使该客户端发起2次连接分别落在两台worker进程上,也会被拒绝。
3.这个内存(zone)设置的意义是什么?是代表本模块所开辟的内存空间吗?就是您举例说的那个碗的大小吗?
另外,您讲到会作用到所有work进程,这是什么意思呢?
作者回复
1、worker进程通常与cpu数量保持一致,所有worker进程即当前master生成的所有worker子进程。
2、nginx中常用的配置指令里,以zone结尾表示开辟的共享内存,可以同时被所有worker进程使用。
58 | access阶段:对用户名密码做限制的auth_basic模块
校验用户名密码是否匹配,来决定是否拒绝请求访问。
HTTP Basic Authentication
image.png模块基本流程
比如我们访问一个url(/) ,nginx首先返回一个401,这个401不会在客户端显示,因为我们注明了WWW-Authenticate: Basic
,使用了这样的协议。浏览器就会弹出一个框让我们输入用户名密码。然后浏览器就会以明文的方式发送给nginx。这个协议本身不保证安全性。当然我们使用了https加密就没问题了。
auth_basic 模块的指令
image.png怎么生成刚刚那种file(auth_basic_user_file) 的文件格式呢?
image.png可以通过apache里面的工具包httpd-tools(yum安装即可)。大概生成后的文件的格式看左半边图。
密码文件(做了简单的base64编码)
image.png示例
image.png image.png当我们提供一些非常简单的页面服务时比如说goaccess界面,想对它做一些安全保护,使用auth_basic是非常快捷的办法。
59 | access阶段:使用第三方做权限控制的auth_request模块
无论我们通过access模块限制ip,或者使用auth_basic模块限制用户名密码,这些都是非常简单的用户验证方式。在我们的生产环境中,我们很有可能有一个动态的web服务器或者相应的一些应用服务器,它们提供更复杂的用户名权限验证。这个时候可通过访问nginx资源时,把这个请求传递给应用服务器,根据应用服务器返回的结果再判断这个请求资源能否继续执行。auth_request模块就可以完成这样的功能。
统一的用户权限验证系统
image.png这个模块默认不编译进去nginx。
生成子请求,子请求的内容与请求的内容是相同的。然后通过反向代理把子请求传递给上游服务,根据上游服务返回的响应再决定是否处理当前这个请求。
auth_request指令,默认是关闭的,如果加上uri,默认会生成一个子请求。这个子请求会访问这个uri。根据这个uri返回的结果决定这个请求是否继续向下执行。
auth_request_set指令,方便我们进一步处理,执行完之后可以设置新的变量。变量的值value还可以含有一些变量。比如说根据上游返回的upstream相关变量,添加到新的变量中($variable)。
例子
image.pngproxy_pass_request_body off,这里没传递body,因为没有必要传。conten-lenght自然为空(没有请求body)。
如果请求成功,会访问,html下面的index.html。如果被8090机器拒绝了呢?会返回8090这台机器返回的错误码。
来看下8090的配置
200的配置
image.png200的情况
image.png403的情况
image.png做这个实验的时候别忘了关闭浏览器缓存。
这个模块对于我们拥有一个统一的鉴权系统是非常有用的
留言问题:
1.auth_request 模块是可以传参数的吧 请求后端的登录接口
作者回复
可以
60 | access阶段的satisfy指令
前面我们提到了access阶段的三个http模块,是不是说任何一个模块拒绝了用户的请求,用户的请求就得不到执行了呢?并不是。是不是这三个模块要严格的按照顺序执行呢?也不是。这是因为nginx的http框架中提供了一个satisfy这样一个指令。这个指令允许我们改变了模块的执行顺序。
satisfy指令
image.pngall或者any是什么意思呢?我们access阶段中有很多模块。satisfy all就是说access、auth_basic、auth_request这三个模块必须放行这个请求。这个请求才能向下执行。任何一个模块拒绝了这个请求,我们都将返回400或500系列的错误给用户。如果是 any呢?虽然我们的执行顺序还是ccess、auth_basic、auth_request,但是只要有任意一个模块它同一这个请求放行了。不管之前的模块拒绝还是之后的模块拒绝,没有关系,我们仍然可以继续执行这个请求。
看下流程图,执行一个access模块,可能会给我们返回三个结果:允许放行、忽略、请求被拒绝。
允许放行分支:判断satisfy的开关,如果配置的all,表示必须所有的access模块都同意放行这个请求才可以(所以继续执行下一个模块)。如果是any就不用考虑后面的access模块是否同意了,直接跳到接下来的postaccess阶段执行就可以了。
忽略分支:我们直接跳到下一个access模块。
请求被拒绝分支:同样判断satisfy开关,如果配置的是all,直接拒绝请求,不用继续执行了,如果是any,虽然当前这个模块拒绝了,也许下一个模块它就会同意放行,所以继续执行access模块。
几个问题
image.png第一个:如果return 指令跟access阶段的指令在一起,那么access阶段还会生效吗?
根据我们刚刚的介绍肯定不会生效。因为return指令,它的生效指令在server_rewrite和rewrite阶段,它们都领先于access阶段。这种配置return指令非常常见,我们配置了return也许放在access阶段前面,也许放在后面。access阶段的指令放在return指令前面access阶段也没有机会执行。
第二个:肯定有影响,比如我们配置了satisfy all,虽然auth_basic是允许的,我们也许没有机会输入用户名密码,因为可能access就拒绝了。
第三个:是可以的。虽然deny all了。但是我们配置的是satisfy any,auth_basic 里面只要输入对了密码,仍然是可以访问的。
第四个:如果把deny all放到 satisfy any之前,可不可以访问到文件呢?可以的。因为没有顺序要求。模块是有执行顺序的,但是配置有没有顺序无关紧要。
第五个:没有机会输入,因为我们配置的是satisfy any。也就是任意一个模块通过就彻底放行了。另外,allow all 是access模块的,它先于auth_basic 模块执行。
satisfy指令,对于我们控制access的行为很有帮助,但也会引起我们很多困惑。熟悉这个指令对我们控制请求的访问权限很有帮助
留言问题
1.感觉最近这些好少用的。不知道使用场景(见识少-.-!)
作者回复
如果用了多个http模块做access访问控制的话,并且需要做“与”以及“或”这种逻辑操作时,才用得上的:-)
2.请问如何根据url参数中的key做限流呢?
例如,对于url http://api.abc.com?key=1234-sdwe-1222-ddw2
根据参数key限制QPS。
如果是集群的情况应该怎么做呢?
作者回复
需要结合两节课一起看:
1、第56节课中,limit_req_zone key中可以把key定义为参数的值。
2、第73课介绍的arg_key变量,可以取出url参数值,http_key变量,可以取出request中header的值。
3、如果是集群,需要编程开发,开源版nginx不支持。可以用openresty,并做lua语言的开发,成本较小。
4.authrequest 是子请求的方式,我的理解是不能满足cas认证的方式,是不是只能通过第三方模块来做了
作者回复
因为生产环境中认证这个流程很复杂,对密码学、数据库、业务特点要求多,特别是当今认证还涉及到各种生物识别技术,让nginx来做是不合适的,所以authrequest的应用场景就是利用了nginx的高效,以及通常是由专业的动态应用服务器做认证的。
5.相当于 或 且 的权限验证
作者回复
对
网友评论