【Nginx专项】高级进阶架构篇-Location、Rewrite及HTTPS
3.Nginx Location指令
Nginx 的location指令是配置请求路由的核心机制,用于定义如何处理不同的 URL 请求。通过配置location指令块,可以决定客户端发来的请求 URI 如何处理(是映射到本地文件还是转发给后端服务)。
3.1 基本语法
location [=|~|~*|^~|@] uri { ... }- 位置:可以在
server块或location块内配置 - 参数说明:
=、~、~*、^~、@为修饰符,用于定义匹配方式uri是要匹配的请求路径
3.2 修饰符类型及优先级
Nginx 的 location 匹配分为五类,优先级从高到低如下:
3.2.1 精确匹配(=)
语法:
location = /path { ... }规则:仅当请求路径与指定路径完全一致时生效,区分大小写
特点:匹配成功后立即停止搜索,优先级最高
示例:
location = /login { proxy_pass http://backend; # 仅匹配 /login,不匹配 /login/ 或 /login.html }
3.2.2 前缀匹配(^~)
语法:
location ^~ /path { ... }规则:对 URL 路径进行前缀匹配,匹配成功后不再进行正则匹配
特点:在正则匹配之前执行,但优先级低于精确匹配
示例:
location ^~ /static/ { root /var/www; # 匹配所有以 /static/ 开头的请求 }
3.2.3 正则匹配
3.2.3.1 区分大小写(~):
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; # 匹配以 .php 结尾的请求,区分大小写 }3.2.3.2 不区分大小写(~*):
location ~* \.(gif|jpg|jpeg)$ { root /data/images; # 匹配图片文件,不区分大小写 }3.3 普通前缀匹配(无修饰符)
语法:
location /path { ... }规则:进行前缀匹配,但在正则匹配之后执行
特点:如果没有正则匹配命中,则选择最长匹配的规则
示例:
location /api/ { proxy_pass http://api_server; }
3.4 通用匹配(/)
语法:
location / { ... }规则:匹配所有请求,相当于 switch 中的 default
特点:优先级最低,作为兜底配置
示例:
location / { root /var/www/html; index index.html; }
3.5 匹配顺序详解
当 Nginx 接收到请求时,按照以下顺序进行匹配:
- 先检查精确匹配(=)
- 检查前缀匹配(^~),找到最长的前缀匹配
- 按配置顺序检查正则匹配(、*)
- 如果没有正则匹配,则使用最长的前缀匹配
- 最后使用通用匹配(/)
3.6 常用场景示例
3.4.1 静态文件服务
server { listen 80; server_name example.com; # 静态资源 location ^~ /static/ { root /var/www; expires 30d; } # 图片文件 location ~* \.(jpg|jpeg|png|gif|ico)$ { root /var/www/images; expires 1y; } # 默认处理 location / { proxy_pass http://backend; } }3.4.2API路由
server { listen 80; server_name api.example.com; # 精确匹配健康检查 location = /health { return 200 'OK'; add_header Content-Type text/plain; } # API v1 location /api/v1/ { proxy_pass http://api_v1_server; } # API v2 location /api/v2/ { proxy_pass http://api_v2_server; } }3.4.3 屏蔽特定路径
# 禁止访问 .git 目录 location ~ /\.git { deny all; return 403; } # 禁止访问敏感文件 location ~* \.(env|log|sql)$ { deny all; return 403; }3.7 重要注意事项
- 匹配顺序很重要:配置文件中 location 的顺序会影响匹配结果,特别是正则匹配
- proxy_pass 末尾斜杠:
- 有斜杠:
proxy_pass http://backend/;- 不携带 location 匹配的路径 - 无斜杠:
proxy_pass http://backend;- 携带 location 匹配的路径
- 有斜杠:
- 调试技巧:可以使用
nginx -T命令查看完整的配置,或在 location 块中添加add_header X-Location "规则名称";便于调试 - 性能考虑:精确匹配和前缀匹配性能最好,正则匹配性能相对较低
3.8 优先级冲突案例
server { listen 80; server_name example.com; # 规则A: 精确匹配 location = /login { echo '规则A: 精确匹配/login'; } # 规则B: 前缀匹配 location ^~ /login { echo '规则B: 前缀匹配/login'; } # 规则C: 正则匹配 location ~ /login { echo '规则C: 正则匹配/login'; } # 规则D: 普通匹配 location /login { echo '规则D: 普通匹配/login'; } }请求/login的匹配结果:
- 优先匹配规则A(精确匹配)
- 规则B、C、D都不会执行
通过合理配置 location 指令,可以实现复杂的请求路由逻辑,是 Nginx 配置中最重要的功能之一。理解其匹配规则和优先级对于正确配置 Nginx 服务器至关重要。
4.Nginx Rewrite–Nginx URL重写
4.1 什么是Rewrite?
Rewrite(URL重写)是Nginx中一个强大的功能模块,用于将传入Web的请求重定向到其他URL的过程。简单来说,就是当用户访问某个URL时,Nginx会根据配置的规则将请求"改写"成另一个URL,然后进行相应的处理。
核心概念:
- URL重定向:将一个URL地址映射到另一个URL地址
- 正则匹配:基于Perl兼容正则表达式(PCRE)进行模式匹配
- 透明性:对用户来说,URL重写通常是透明的(除了301/302跳转)
4.2Rewrite的主要作用?
安全性提升
- 隐藏真实目录结构:避免暴露服务器内部文件路径
- 防止恶意攻击:重写可疑的URL请求
- 统一入口:将所有请求重定向到统一的安全入口
SEO优化
- URL权重集中:将多个相似URL重定向到首选URL,避免权重分散
- 友好URL:将动态URL重写为静态、易读的URL格式
- 301永久重定向:网站改版时保持搜索引擎排名
网站维护
- 平滑迁移:网站结构调整时保持旧URL可用
- A/B测试:将不同用户重定向到不同版本的页面
- 负载均衡:根据条件将请求重定向到不同的后端服务器
4.3Rewrite指令语法
4.3.1 基本语法
rewrite regex replacement [flag];4.3.2 参数说明
- regex:正则表达式,用于匹配请求的URI
- replacement:重写后的URL路径
- flag:标志位,控制重写行为(可选)
常用 flag 标记:
| Flag | 说明 | HTTP状态码 |
|---|---|---|
last | 停止当前rewrite,重新搜索location | 内部重写 |
break | 停止当前rewrite,继续处理请求 | 内部重写 |
redirect | 临时重定向 | 302 |
permanent | 永久重定向 | 301 |
4.4Rewrite条件判断
4.4.1~*正则匹配
# 仅匹配以小写 .php 结尾的文件 location / { if ($request_uri ~* \.php$) { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; } }说明:
~*表示区分大小写的正则匹配- 只匹配
.php(小写),不匹配.PHP或.Php - 应用场景:严格安全控制,防止通过大小写绕过PHP处理
4.4.2!~非正则匹配(区分大小写)
# 如果请求路径不是以 /admin/ 开头(区分大小写) location / { if ($request_uri !~ ^/admin/) { # 只有非管理员路径才应用此规则 add_header X-Non-Admin "1"; } }说明:
!~表示不匹配指定的正则表达式(区分大小写)/Admin/会被认为是不匹配的(因为是大写A)- 应用场景:区分大小写的访问控制
4.4.3!~*非正则匹配(不区分大小写)
# 如果请求路径不是以 /admin/ 开头(不区分大小写)location /{if($request_uri!~* ^/admin/){# 所有非管理员路径(无论大小写)都应用此规则add_header X-Non-Admin"1";}}说明:
!~*表示不匹配指定的正则表达式(不区分大小写)/Admin/、/ADMIN/都会被认为是匹配的,不会执行此规则- 应用场景:用户友好的访问控制(不区分大小写)
4.4.4-f和!-f(用来判断是否存在文件)
# 如果文件存在,则直接返回location /{if(-f$request_filename){# 文件存在,直接返回break;}# 文件不存在,重写到index.phprewrite ^/(.*)$ /index.php?path=$1last;}说明:
-f:检查文件是否存在!-f:检查文件不存在- 应用场景:单页面应用(SPA)的路由处理
4.4.5-d和!-d(用来判断是否存在目录)
# 如果目录存在,则添加 trailing slashlocation /{if(-d$request_filename){rewrite ^/(.*[^/])$ /$1/ permanent;}}说明:
-d:检查目录是否存在!-d:检查目录不存在- 应用场景:自动添加目录尾部斜杠
4.4.6-e和!-e(用来判断是否存在文件或目录)
# 如果文件或目录不存在,则重定向到404页面location /{if(!-e$request_filename){rewrite ^ /404.html last;}}说明:
-e:检查文件或目录是否存在!-e:检查文件或目录不存在- 应用场景:自定义404错误处理
4.4.7-x和!-x(用来判断是否存在文件是否可执行)
# 检查脚本是否可执行location /cgi-bin/{if(!-x$request_filename){return403;}# 如果可执行,继续处理fastcgi_pass127.0.0.1:9000;include fastcgi_params;}5.HTTPS协议
5.1 基本概念
HTTPS(Hypertext Transfer Protocol Secure,超文本传输安全协议)是HTTP协议的安全版本。它在HTTP协议的基础上增加了SSL/TLS(Secure Sockets Layer/Transport Layer Security)加密层,用于保护网络通信的安全性。HTTPS的核心目标是解决HTTP协议在数据传输过程中存在的安全缺陷。
5.2HTTPS和HTTP的核心区别
| 对比维度 | HTTP | HTTPS |
|---|---|---|
| 安全性 | 明文传输,数据可被窃听、篡改 | 加密传输,保护数据机密性和完整性 |
| 端口 | 80端口 | 443端口 |
| 协议层 | 应用层协议 | HTTP + SSL/TLS安全层 |
| 身份验证 | 无身份验证机制 | 通过数字证书验证服务器身份 |
| 数据完整性 | 无完整性校验 | 通过MAC(消息认证码)确保数据完整性 |
5.3HTTPS的工作原理
HTTPS的安全性主要通过以下机制实现:
5.3.1 SSL/TLS握手过程
- 客户端Hello:客户端向服务器发起连接请求,包含支持的加密套件和协议版本
- 服务器Hello:服务器选择加密套件,返回服务器证书(包含公钥)
- 证书验证:客户端验证服务器证书的有效性(通过CA证书链)
- 密钥交换:
- 客户端生成随机的预主密钥
- 使用服务器的公钥加密预主密钥并发送给服务器
- 服务器使用私钥解密获得预主密钥
- 生成会话密钥:双方基于预主密钥生成相同的对称加密密钥
- 安全通信:使用对称密钥进行加密数据传输
5.3.2 加密机制
HTTPS采用混合加密策略:
- 非对称加密:仅用于证书验证和密钥交换阶段,确保密钥安全传输
- 对称加密:用于实际数据传输,效率高,适合大量数据加密
5.4HTTPS的优势与局限性
5.4.1 优势
- 数据安全:保护用户隐私和敏感信息
- 身份验证:防止钓鱼网站和中间人攻击
- SEO友好:搜索引擎优先收录HTTPS网站
- 用户信任:浏览器地址栏显示安全标识(锁图标)
5.4.2 局限性
- 性能开销:加密解密过程增加CPU开销和延迟
- 配置复杂:需要正确配置证书和服务器
- 成本:部分高级证书需要付费
- 并非万能:不能防止应用层攻击(如XSS、SQL注入)
5.5HTTPS模拟实操
5.5.1 私有CA
5.5.1.1创建证书
[root@Nginx-1 ~]# mkdir -p /etc/nginx/ssl[root@Nginx-1 ~]# openssl req -utf8 -new -key /etc/nginx/ssl/server.key -x509 -days 365 -out /etc/nginx/ssl/server.crt[root@Nginx-1 ~]# ll /etc/nginx/ssl/-rw-r--r--1root root1407Apr1517:23 server.crt -rw-r--r--1root root0Apr1517:10 server.csr -rw-r--r--1root root1708Apr1517:09 server.key5.5.1.2 创建网页并查看状态
[root@Nginx-1 ~]# mkdir /Test[root@Nginx-1 ~]# echo "HTTPS HTTPS HTTPS" > /Test/index.html[root@Nginx-1 ~]# vim /etc/nginx/conf.d/Test.confserver{listen443ssl;server_name172.25.254.44;ssl_certificate /etc/nginx/ssl/server.crt;ssl_certificate_key /etc/nginx/ssl/server.key;location /{root /Test;index index.html;}}[root@Nginx-1 ~]# nginx -t[root@Nginx-1 ~]# systemctl restart nginx# 浏览器访问:https://172.25.254.44