技术解析

Nginx if is evil。。。这种情况下怎么避免用 if
0
2021-05-25 15:41:46
idczone

需要记录 nginx 的 post data

所以需要把 post 单独拿出来。但是网站又有上传头像功能,于是 post data 里把上传的图片也记录了,导致 log 超大

于是想用下面的方法来实现,简单说如果发现 uri 里带 upload ,就内部跳转到不记录 post data 的部分,如果发现是 post 请求,则跳转到记录 post data 的部分

	location ~ \.php$ {
		try_files $国外服务器uri =404;
		if ($arg_mod = "upload" ) {
			return                 485;
			break;
		}
		if ($request_method = POST){
			return                 484;
			break;
		}
		error_page               484 = @post;
		error_page               485 = @flash;
		fastcgi_pass   backend;
	}
	location @post{
		internal;
		access_log /log/post.log  postlog;
		try_files $uri =404;
		fastcgi_pass   backend;
		}
	location @flash{
		internal;
		access_log /log/flash.log  main;
		try_files $uri =404;
		fastcgi_pass   backend;
		}

问题就来了, if is evil ,上面的这种写法应该是不推荐 那么,有没有什么更好的方法来实现这个需求呢?


我也有这个疑问。我不是 Nginx 配置专家,但是网上查过,好像查不到把 POST 独立出来作为一个 location 的方法。

可以判断 Content-Type 是不是等于 multipart/form-data ,是就不记录
建议你们用 php 来记录, nginx 不是做这个事的

我这个方法其实已经独立出来了,但是必然用到 if 了。。。所以想集思广益看看有没有更好的办法

php 记录不是最好的方法
我们记录 post 内容其实也是出于安全的考虑, post 都记录下来,这样如果被黑什么的,可以根据 post 数据定位漏洞
而使用 php 记录的话,太容易被绕过了。

1. 用 rewrite 另外弄一个 URL 接收 POST 上传的图片。
2. location 那个 URL 。

如果一定要在 nginx 里面做这个的话,他们似乎都是加上 lua 模块用 lua 写这些逻辑的

用 lua 很方便
趁机练习了一下
https://gist.github.com/sagnitude/9b8e8f7ae09756acb521f2e5531935ee


if arg then
ngx.exec("@flash")
else
这个地方应该是 if arg_mod = "upload"吧。
lua 目前还没学,先请教下

local arg = ngx.var.arg_upload 就是取 uri 参数

收到
是不是 lua 里的 if 可以多个条件

elseif? https://www.lua.org/manual/5.3/manual.html#3.3.4


不好意思另外一个问题
lua 怎么获取 user-agent 做判断? 试着找了下文档似乎需要读取 header?

对, ua 是 http header , ngx.req.get_headers()['User-Agent'],还有个贵一点的方法 ngx.var.http_user_agent

文档在这 https://github.com/openresty/lua-nginx-module

楼主你把区分的因素放到 path 里,而不是放到$arg_xxx 里,这样你就可以通过 location path 来匹配两种规则。
比如:
location ~ /upload {
access_log /log/post.log postlog;
try_files $uri =404;
fastcgi_pass backend;
}
location / {
access_log /log/flash.log main;
try_files $uri =404;
fastcgi_pass backend;
}

这个不现实
现在各种 php 都是统一入口,比如说像 wp ,是 index.php?**
根据后面的参数来执行各种操作。所以只能通过 uri 来判断

用 rewrite 转一下呢

数据地带为您的网站提供全球顶级IDC资源