Nginx location 匹配的是解码后的 URI,故空格应直接写为字面空格(如 file name\.css),而非 %20;需防范双重编码、非法编码等风险,推荐前端规范化路径。

直接在 location 中匹配带空格或特殊字符的 URL,不能按原始字符串写,因为 Nginx 在匹配前会先对请求 URI 做一次解码(如 %20 → 空格),而正则表达式匹配的是解码后的路径。所以关键不是“怎么写空格”,而是“怎么应对解码后的表现和潜在风险”。
空格和常见特殊字符的实际匹配行为
用户请求 /static/file name.css,浏览器会自动编码为 /static/file%20name.css;Nginx 接收到后默认解码成 /static/file name.css,再用这个解码后的字符串去匹配 location。
- location
~ \.css$仍能命中 —— 因为解码后结尾仍是.css - location
~ file name\.css也能命中 —— 正则中直接写空格即可(但不推荐,可读性差且易出错) - location
~ file%20name\.css不会命中 —— 因为匹配的是解码后的路径,不是原始编码串
需要精确匹配编码名时的写法
如果必须按原始编码形式匹配(例如拦截特定恶意编码),就得让正则去匹配解码前的字节序列,这时要写成百分号编码格式,并注意大小写与转义:
- 匹配
style(v1).css的编码形式style%28v1%29.css,正则应写为:location ~ style%28v1%29\.css$ { ... } -
%后跟两个十六进制字符([0-9A-Fa-f]{2})才构成合法编码,正则中%本身无需反斜杠转义,除非后面紧接字母/数字可能被误解析 - 避免用
~*(忽略大小写),因为%28和%28大小写一致,但若混入%e4%bd%a0这类 UTF-8 编码,大小写敏感性会影响中文匹配
安全拦截非法或危险编码
空格本身不危险,但空格常伴随双重编码、目录遍历、空字节等攻击模式。应在 location 匹配前就阻断:
- 拦截典型高危模式:
if ($uri ~ "\.\./|%00|%(2e){2}") { return 403; } - 拒绝非法编码(如
%GG、%2z):if ($request_uri ~ "%[^0-9A-Fa-f]{2}") { return 400; } - 清理分号干扰(防止绕过):
rewrite ^(/[^;]*)\;.*$ $1 break;
更稳妥的长期策略
依赖 location 匹配特殊字符终究是兜底手段。生产环境建议从源头减少这类路径:
- 前端生成资源路径时,用短横线或下划线替代空格(
file-name.css而非file name.css) - 后端返回的跳转或链接,统一做路径规范化(如把空格转为
%20并确保只编码一次) - 对静态资源路径,用符号链接代替含空格的真实路径,Nginx 只需匹配干净的英文路径











