这周在项目中遇到一个问题:由于咱们前端打包的时分把静态文件的.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种:

  1. 无符号:也便是匹配符号为空,算是一种前缀匹配,如 location / {}
  2. =:表明精确匹配,如location = /static/abc.png {}
  3. ^~: 表明优先前缀匹配,如location ^~ /static/js/ {}
  4. ~: 表明区别大小写的正则匹配,如location ~ /static/js/ {}
  5. ~*: 表明不区别大小写的正则匹配,如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这儿的规矩进行了一个总结,而且画了一个流程图来体现:

总算了解了Nginx装备中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

匹配过程如下:

总算了解了Nginx装备中location规矩的优先级问题

/static/js/4.png这个地址仅被两个优先前缀匹配,所以直接回来优先前缀匹配最长的/static/js/的404

/static/js/css6/4.png这个地址一起被两个优先级前缀匹配,所以选择最长的回来404

匹配过程如下:

总算了解了Nginx装备中location规矩的优先级问题

这3个地址的匹配我最开始非常不了解,特别是第1个和第3个的比照,而且把这个疑问发到了V站进行评论,也正是这个评论,让我了解了这儿的规矩。

学以致用

经过上面的学习,我知道了正则的规矩收效的条件,所以我想到了解决项目上问题的方案,之前我装备的正则不收效是由于地址被优先前缀匹配到了,所以直接回来了,根本不会到正则判别这一步,所以为了使正则收效,我需求额定增加一个无符号前缀匹配才行,我的解决方案是这样的:

location ~* .(css|js).map$ {
    return 403;
}
location /itsc-mobile/static/js/ {
    proxy_pass http://logic.itsc_mobile/;
}

我在拓宽文件中增加了两个规矩,第一个规矩自然是正则匹配了,第二个规矩是一个无符号前缀匹配规矩,这个规矩需求比原本的优先级前缀匹配规矩长,这样才能走到这儿,进而走向正则匹配。

总结

其实在项目里边经常会遇到需求装备Nginx规矩的工作,而咱们项目里边装备文件又多,规矩根本就理不清楚,所以之前装备的时分经常也是不断试探。经过了这次的学习,我总算是理清楚了location的规矩,也经过了验证是了解正确的,后续再遇到Nginx装备规矩不收效或许产出抵触,就能够按照这个思路去定位解决了。

本文链接: tendcode.com/subject/art…