这周在项目中遇到一个问题:由于咱们前端打包的时分把静态文件的.map文件也上传到了出产环境中,导致这些.map文件能够被拜访下载,因而被定性为“有源码泄露的安全危险问题”。因而,需求禁用这些.map文件的拜访,所以决定用Nginx增加装备来禁用,可是设置过程中发现怎样都不收效,最后经过了我的各种查找和发问,总算搞清楚了Nginx的装备中location规矩的收效规矩,终究也解决了问题。
问题背景
项目需求
基于上面说到的问题,这儿还有一个限制条件:咱们的项目中有个许多Nginx装备,我不能修正默许的装备,只能在默许装备的一个拓宽装备中增加新装备,来解决.map文件可拜拜访题。
咱们的这个默许装备要害内容如下:
server {
...
include conf.d/console*.conf.custom;
location ^~ /itsc-mobile/ {
proxy_pass http://logic.itsc_mobile/;
}
...
}
其他内容就省掉了,其实便是说我不能修正这个默许文件,可是能够增加一个console*.conf.custom
文件来增加额定的装备。
我要做的便是让用户无法拜访/itsc-mobile/static/js/main.45d35777.js.map
这种地址,也便是以.js.map
或许.css.map
结束的文件,可是不能影响正常的js和css的拜访,比如/itsc-mobile/static/js/main.45d35777.js
需求正常拜访。
我的做法
我想到的方案是增加一个正则的规矩,匹配.js.map
或许.css.map
结束的文件就回来403,这样就能够阻止用户拜访这种文件了。
所以我在额定装备文件console-ext.conf.custom中增加了如下规矩:
location ~* .(css|js).map$ {
return 403;
}
可是经过验证,发现这个规矩根本就不收效,期初以为是我装备的方位不对,后边经过一番验证发现跟装备的方位不要紧,便是正则不收效。
所以带着这个问题,我经过了一番查找和求证,总算搞清楚了Nginx装备里边location的规矩的收效规矩。
location的语法
这儿我根据网上搜到的一些文章,还有官方文档的介绍,自己了解后对location的的语法进行了总结。
这儿只评论下面这种由4个部分组成的语法, 这4个组成部分分别是: location要害字 匹配方法符号(可省掉) 匹配规矩 如何处理, 这个最复杂也是最常用, 咱们只评论这个。
格式大概是这样的:
location [ = | ^~|~ | ~* | ] uri { ... }
这儿的匹配符号有5种:
- 无符号:也便是匹配符号为空,算是一种前缀匹配,如
location / {}
-
=
:表明精确匹配,如location = /static/abc.png {}
-
^~
: 表明优先前缀匹配,如location ^~ /static/js/ {}
-
~
: 表明区别大小写的正则匹配,如location ~ /static/js/ {}
-
~*
: 表明不区别大小写的正则匹配,如location ~* /static/js/ {}
location语法的优先级
我这儿把这5种规矩分红三类,分别是精确匹配、前缀匹配(无符号和优先前缀匹配),正则匹配。
精确匹配
格式如下:
location = /static/abc.png {
return 403;
}
精确匹配是要求恳求地址跟匹配项完全一致才算匹配成功,所以这种匹配是优先级最高的,只要匹配成功,就不会再进行其他规矩的判别,直接回来。
前缀匹配
首要是无符号的前缀匹配:
location /static/js/css/ {
return 405;
}
location /static/js/ {
return 405;
}
然后是有符号的前缀匹配,这种我称之为优先前缀匹配
location ^~ /static/js/ {
return 404;
}
这两个的优先级规矩是:命中任何一个前缀匹配的话,还会继续往下去进行规矩匹配,而且会从这两个规矩中选择匹配到的最长的前缀作为成果,而假如长度相同,那么优先级前缀优先,此刻直接回来优先前缀匹配,假如是无符号匹配的更长,则继续去匹配正则规矩。
一个例子:/static/js/css/abc
这个地址一起被上面的两个前缀规矩匹配,可是很明显无符号的规矩能够匹配到/static/js/css/
比有符号的匹配前缀/static/js/
长,所以会选择/static/js/css/
最为暂时回来规矩,进一步去找正则规矩。
而/static/js/abc
这个地址也一起被上面的规矩匹配,可是两个都是匹配到/static/js/
,长度一样,此刻有符号的优先级就更高,而且不会继续找正则匹配,直接回来。
正则匹配
格式如下:
location ~* .(css|js).map$ {
return 402;
}
正则匹配的优先级相比照较低,从上面的前缀匹配也能看到,当无符号的前缀匹配到的情况下才会进行正则匹配,而且假如此刻正则匹配到了,那么会取正则的成果,否则取无符号前缀匹配的成果
总结
我经过咨询和学习,对location这儿的规矩进行了一个总结,而且画了一个流程图来体现:
有如下结论:
- 首要,不同规矩在文件中的次序对规矩的匹配不受影响,只有同类型规矩的次序至上到下进行匹配时是先匹配先收效的
- 精确匹配优先级最高,只要匹配到就立即回来,不会进行下一步匹配
- 前缀匹配中会取匹配到的最长前缀作为预选,当无符号的匹配最长时,还需求进行正则匹配,当优先前缀最长时,直接回来
- “正则匹配的优先级很低”这个说法其实是不精确的,由于当匹配能到达正则匹配这儿的时分,正则匹配的优先级便是最高的,只要匹配就回来,所以真正的问题是匹配会不会到正则匹配这儿
一个典型案例
有如下装备文件:
server {
listen 12080;
server_name abc.com;
access_log /var/log/nginx/test.access.log;
error_log /var/log/nginx/test.error.log;
location ~* .png$ {
return 402;
}
location / {
return 400;
}
location /static/js/css/ {
return 405;
}
location ^~ /static/ {
return 401;
}
location ^~ /static/js/ {
return 404;
}
location = /static/abc.png {
return 403;
}
}
请写出下面的地址的回来码(能够在这个网站上面进行验证 nginx.viraptor.info/):
/static/js/css/4.png
这个地址会回来402,由于它一起被无符号前缀和有符号前缀匹配到,可是无符号前缀/static/js/css/
更长,此刻就继续进行正则匹配,发现能够被正则匹配到,所以回来了正则匹配的状态码402
匹配过程如下:
/static/js/4.png
这个地址仅被两个优先前缀匹配,所以直接回来优先前缀匹配最长的/static/js/
的404
/static/js/css6/4.png
这个地址一起被两个优先级前缀匹配,所以选择最长的回来404
匹配过程如下:
这3个地址的匹配我最开始非常不了解,特别是第1个和第3个的比照,而且把这个疑问发到了V站进行评论,也正是这个评论,让我了解了这儿的规矩。
学以致用
经过上面的学习,我知道了正则的规矩收效的条件,所以我想到了解决项目上问题的方案,之前我装备的正则不收效是由于地址被优先前缀匹配到了,所以直接回来了,根本不会到正则判别这一步,所以为了使正则收效,我需求额定增加一个无符号前缀匹配才行,我的解决方案是这样的:
location ~* .(css|js).map$ {
return 403;
}
location /itsc-mobile/static/js/ {
proxy_pass http://logic.itsc_mobile/;
}
我在拓宽文件中增加了两个规矩,第一个规矩自然是正则匹配了,第二个规矩是一个无符号前缀匹配规矩,这个规矩需求比原本的优先级前缀匹配规矩长,这样才能走到这儿,进而走向正则匹配。
总结
其实在项目里边经常会遇到需求装备Nginx规矩的工作,而咱们项目里边装备文件又多,规矩根本就理不清楚,所以之前装备的时分经常也是不断试探。经过了这次的学习,我总算是理清楚了location的规矩,也经过了验证是了解正确的,后续再遇到Nginx装备规矩不收效或许产出抵触,就能够按照这个思路去定位解决了。