一、重定向与Nginx的rewrite
1、重定向与rewrite的关系
在 Nginx 中,rewrite
指令用于修改请求的 URL。它允许你修改请求的路径并进行内部处理或者外部重定向。
重定向是将客户端(如浏览器)指向一个新的 URL,这会改变用户的地址栏中的 URL 并发起新的请求。在 Nginx 中,重定向与 rewrite
的主要区别在于:
-
重定向:会改变用户的地址栏,使用 301(永久重定向)或 302(临时重定向)等状态码,告知浏览器访问新的 URL。
-
rewrite
:在服务器内部修改请求的 URI,但用户的地址栏不会变化。这通常用于将请求路由到不同的处理路径。
重定向会影响用户的浏览器,而 rewrite
主要用于后台处理请求。
Nginx 的 rewrite
指令可以用于实现重定向功能。虽然 rewrite
通常用于在服务器内部重写 URL,而不改变用户的浏览器地址栏,但你也可以使用 rewrite
指令来触发重定向。具体来说,通过 rewrite
指令,你可以使用 redirect
或 permanent
标志来执行重定向。
Nginx 的 rewrite
指令可以有以下两种重定向模式:
-
临时重定向:使用
redirect
标志来创建一个 302 临时重定向,告诉浏览器请求新的 URL,但不永久更新。 -
永久重定向:使用
permanent
标志来创建一个 301 永久重定向,告诉浏览器和搜索引擎新的 URL 是永久的,并更新其索引。
示例
临时重定向(302)
location /old-page {
rewrite ^/old-page$ /new-page redirect;
}
在这个示例中,当用户请求 example.com/old-page
时,Nginx 会返回一个 302 临时重定向,指向 example.com/new-page
,用户的地址栏将更新为新的 URL。
永久重定向(301)
location /old-page {
rewrite ^/old-page$ /new-page permanent;
}
在这个示例中,当用户请求 example.com/old-page
时,Nginx 会返回一个 301 永久重定向,指向 example.com/new-page
,用户的地址栏也会更新为新的 URL。浏览器和搜索引擎会将新的 URL 视为资源的新位置,并在未来的请求中直接访问新 URL。
总结
rewrite
指令:主要用于在服务器内部处理 URL,但可以用来实现重定向。- 重定向:使用
redirect
或permanent
标志来改变用户的浏览器地址栏中的 URL。 - 使用场景:重定向适合需要改变用户和搜索引擎的 URL 的场景,而
rewrite
更适合处理内部 URL 结构。
通过这些功能,你可以根据需要在 Nginx 配置中灵活地实现 URL 处理和重定向。
2、rewrite的使用场景:
1)地址跳转
如:baidu.com → https://www.baidu.com
2)协议跳转
如:http://baidu.com/ → https://www.baidu.com
3)伪静态,便于搜索引擎的录入
注:什么是伪静态
Nginx 的
rewrite
指令用于将动态 URL 转换为静态 URL,这种技术被称为伪静态。伪静态的主要目的是使 URL
更简洁、更具可读性,同时有助于 SEO(搜索引擎优化)和用户体验。它允许动态网站用静态页面的 URL 模式呈现内容,从而让 URL
更友好,更容易记住和分享。一、伪静态的应用场景
在实际生产环境中,伪静态常用于以下几种场景:
- 博客和新闻网站:将文章的 ID 转换为简洁的文章标题或日期格式。
- 电商网站:将产品的动态 URL 转换为包含产品名称或类别的静态 URL。
- 内容管理系统(CMS):将文章、页面等动态内容的 URL 转换为更易于用户理解和搜索引擎抓取的 URL。
二、实际生产中的例子
1. 博客文章
假设你有一个博客网站,文章的动态 URL 可能是
http://example.com/index.php?id=123
。为了使 URL
更友好,可以将其伪静态为http://example.com/post/2024/some-article-title
。Nginx 配置:
server {
listen 80;
server_name example.com;
location / {
# 将 /post/2024/some-article-title 伪静态化为 /index.php?year=2024&slug=some-article-title
rewrite ^/post/([0-9]+)/([a-zA-Z0-9_-]+)$ /index.php?year=$1&slug=$2 last;
}
}
- 请求 URL:
http://example.com/post/2024/some-article-title
- 重写到:
http://example.com/index.php?year=2024&slug=some-article-title
2. 电商产品
对于电商网站,产品的动态 URL 可能是
http://example.com/product.php?id=456
。可以将其伪静态为
http://example.com/product/some-product-name
。Nginx 配置:
server {
listen 80;
server_name example.com;
location / {
# 将 /product/some-product-name 伪静态化为 /product.php?name=some-product-name
rewrite ^/product/([a-zA-Z0-9_-]+)$ /product.php?name=$1 last;
}
}
- 请求 URL:
http://example.com/product/some-product-name
- 重写到:
http://example.com/product.php?name=some-product-name
3. 内容管理系统(CMS)
在 CMS 中,页面的动态 URL 可能是
http://example.com/page.php?id=789
。伪静态化后,URL
可能变为http://example.com/about-us
。Nginx 配置:
server {
listen 80;
server_name example.com;
location / {
# 将 /about-us 伪静态化为 /page.php?id=789
rewrite ^/about-us$ /page.php?id=789 last;
}
}
- 请求 URL:
http://example.com/about-us
- 重写到:
http://example.com/page.php?id=789
三、伪静态的好处
- 更好的用户体验:简洁的 URL 更容易记住和分享。
- SEO 优化:搜索引擎倾向于友好的 URL,有助于提高搜索排名。
- 提高网站安全性:隐藏实际的文件路径和参数,减少潜在的安全风险。
通过配置伪静态 URL,Nginx 可以将用户请求重写为更有意义的 URL,同时继续提供动态内容。这不仅优化了用户体验,也有助于网站的SEO 表现。
注:伪静态与SEO
伪静态(也称为伪静态化)和SEO(搜索引擎优化)有着密切的关系。伪静态主要是为了提高网页的可读性和搜索引擎友好性,而SEO则涉及到通过各种手段提升网页在搜索引擎结果中的排名。下面是伪静态和SEO之间的具体关系及其影响:
1. 什么是伪静态?
伪静态是指将动态网页的 URL 转换为看起来像静态网页的 URL。虽然这些 URL
仍然由服务器动态生成内容,但它们的形式更像静态文件。例如:
- 动态 URL:
example.com/index.php?id=123
- 伪静态 URL:
example.com/products/123.html
2. 伪静态对 SEO 的影响
提高可读性:
- 伪静态 URL 通常更简洁、直观,易于理解。例如,
example.com/products/123.html
比example.com/index.php?id=123
更容易被用户和搜索引擎理解。这种简洁的 URL
可以提高用户的点击率(CTR),因为用户更容易理解和记住这样的链接。关键词优化:
- 伪静态 URL 可以包含关键词,从而提升相关页面的搜索引擎排名。例如,
example.com/shoes/men-running-shoes.html
比example.com/product.php?category=shoes&name=men-running-shoes
更有利于搜索引擎优化,因为关键词直接出现在 URL 中。提高抓取效率:
- 搜索引擎的爬虫(crawler)更容易抓取和索引结构清晰的 URL。伪静态 URL 的清晰结构帮助爬虫更好地理解网站的层次和内容,提高网页的抓取效率。
减少重复内容问题:
- 动态 URL 可能会导致内容重复问题,因为不同的参数组合可能会显示相同的内容。伪静态化可以减少这种情况,因为每个 URL 指向唯一的内容,有助于避免内容重复问题。
增强用户体验:
- 伪静态 URL 通常更美观,对用户更友好。良好的用户体验(如更简洁的 URL)可以间接影响 SEO,因为搜索引擎越来越重视用户体验作为排名因素。
3. 如何实现伪静态
伪静态的实现方式因服务器类型而异,常见的实现方法包括:
- Apache: 使用
.htaccess
文件和mod_rewrite
模块来定义重写规则。- Nginx: 配置
rewrite
指令来实现 URL 重写。- IIS: 使用 URL 重写模块来处理 URL 的转换。
示例(Apache):
RewriteEngine On
RewriteRule ^products/([0-9]+)\.html$ /index.php?id=$1 [L]
4. 注意事项
- 保持一致性: 确保所有的 URL 都一致地使用伪静态化,避免混合使用动态和伪静态 URL。
- 处理重定向: 设置 301 永久重定向,以确保旧的动态 URL 不会造成 404 错误,并且将权重传递给新的伪静态 URL。
- 测试: 定期检查伪静态 URL 是否正确工作,并确保没有出现抓取问题或内容重复问题。
总结
伪静态是 SEO 优化中的重要一环。它通过提高 URL
的可读性和结构化,有助于提升搜索引擎对网站的理解,从而可能提高网页的排名。通过合理配置伪静态 URL,并结合其他 SEO
技巧,可以有效地提升网站的搜索引擎表现。
二、Nginx的rewrite的配置语法
0、rewrite指令的使用
1)语法
rewrite
指令的作用
rewrite
指令主要用于重写请求 URI。它允许你修改请求的路径并进行内部处理或者外部重定向。rewrite
指令的格式如下:
rewrite regex replacement [flag];
其中:
regex
是用于匹配 URI 的正则表达式。replacement
是将匹配的 URI 替换成的新 URI。flag
是可选的,用于指定重写的行为,比如last
、break
、redirect
、permanent
等。
内部重写与外部重定向
-
内部重写:
rewrite
指令用于在 Nginx 内部将请求路径重写为另一个路径,但请求仍然在同一个服务器上进行处理,不会改变请求的域名或协议。例如:
location / { rewrite ^/old_path /new_path last; }
这里
/old_path
会被内部重写为/new_path
,并且请求仍然在同一个 Nginx 服务器上处理。 -
外部重定向:当你希望将请求重定向到另一个服务器或不同的协议时,可以使用
redirect
或permanent
标志,这将指示 Nginx 返回一个 HTTP 重定向响应给客户端。例如:
location / { rewrite ^/old_path https://www.example.com/new_path redirect; }
这里
redirect
会使 Nginx 返回一个 302 临时重定向响应,客户端会被重定向到https://www.example.com/new_path
。
rewrite /test_rewrite_redirect https://www.baidu.com redirect;
这个配置实际上是一个外部重定向。rewrite
指令在这里的作用是将匹配到的 URI /test_rewrite_redirect
重定向到 https://www.baidu.com
。redirect
标志表示 Nginx 应该返回一个 HTTP 重定向响应(默认为 302 临时重定向),让客户端访问新的 URL。
总结
rewrite
指令可以用于内部路径重写,也可以用于外部重定向,具体取决于使用的标志。- 当使用
redirect
或permanent
标志时,rewrite
会执行一个外部重定向,改变请求的协议和域名。 - 内部重写通常不会改变协议和域名,而外部重定向会。
因此,虽然 rewrite
主要用于内部路径处理,但在使用 redirect
或 permanent
标志时,它也可以改变请求的协议和域名,进行外部重定向。
2)例子分析
例1:
rewrite ^(.*)$ /page/maintain.html break;
注:
在 Nginx 的配置中,rewrite ^(.*)$ /page/maintain.html break;
这行指令使用了正则表达式来匹配和重写请求的 URI。我们来逐部分解释这个配置的含义。
正则表达式部分:^(.*)$
-
^
:表示正则表达式的开始位置。这意味着匹配从 URI 的开头开始。 -
(.*)
:这是一个捕获组,.*
表示匹配任意字符(.
)零次或多次(*
)。因此,(.*)
匹配整个 URI 的内容,并将其捕获到一个组中。这个捕获组实际上可以匹配任何内容。 -
$
:表示正则表达式的结束位置。这意味着匹配到 URI 的结尾。
配置说明
rewrite ^(.*)$ /page/maintain.html break;
-
^(.*)$
:这个正则表达式匹配任何 URI。无论请求的 URI 是什么,它都会被匹配,因为.*
可以匹配任何字符,包括空字符串。 -
/page/maintain.html
:这是重写后的目标 URI。无论原始 URI 是什么,请求都会被重写到这个固定的 URI/page/maintain.html
。 -
break
:这个标志告诉 Nginx 在执行重写后停止进一步的重写规则处理。换句话说,一旦这个rewrite
指令匹配成功并执行重写,Nginx 将不再应用其他rewrite
指令。
作用
这个配置的作用是将所有请求的 URI 都重写为 /page/maintain.html
。无论用户请求的是哪个路径,最终都会被重定向到 /page/maintain.html
页面。
举例
- 请求路径
/some/path
被重写为/page/maintain.html
。 - 请求路径
/another/page
被重写为/page/maintain.html
。 - 请求路径
/
也被重写为/page/maintain.html
。
break
标志确保一旦匹配到这个 rewrite
规则,Nginx 不会继续检查其他可能的 rewrite
规则,这使得所有请求都被重写到指定的路径 /page/maintain.html
。
错误用法分析:
rewrite http://www.testredirect.com/test_nginx_rewrite/test_rewrite_redirect https://www.baidu.com redirect;
这种写法是不正确的。rewrite
指令的第一个参数必须是一个正则表达式,用于匹配请求 URI,而不是完整的 URL。你的目标是将请求 URI /test_nginx_rewrite/test_rewrite_redirect
重定向到 https://www.baidu.com
可以使用配置,因为它使用了正则表达式匹配请求 URI:
rewrite ^/test_nginx_rewrite/test_rewrite_redirect$ https://www.baidu.com redirect;
这个配置的意思是:当请求的 URI 完全匹配 /test_nginx_rewrite/test_rewrite_redirect 时,将其重定向到 https://www.baidu.com。
1、Rewrite的flag介绍
flag | 使用 |
---|---|
redirect | 适用于302状态的应用 |
permanent | 适用于301状态的应用 |
last | 表示停止处理当前的 rewrite 规则,继续处理当前位置后的配置,而不是重新匹配新的 URI。适用于你只希望在当前的 location 区块中处理重写。 |
break | 表示这是最后一个重写规则,Nginx 将重新开始处理配置文件中的其他匹配规则。适用于需要重新匹配新 URI 的情况。 |
2、测试Rewrite的flag——redirect
1)错误配置:
:server{
listen 80;
server_name www.testredirect.com;
index index.html;
root /test_nginx_rewrite;
location /test_nginx_rewrite/test_rewrite_redirect {
rewrite www.testredirect.com/test_nginx_rewrite/test_rewrite_redirect https://www.baidu.com redirect;
}
}
2)正确配置:
配置的语法存在问题,rewrite
指令中的目标 URL 应该是使用正则表达式的相对路径,而不是绝对路径。正确的语法应为:
server {
listen 80;
server_name www.testredirect.com;
index index.html;
root /test_nginx_rewrite;
location /test_nginx_rewrite/test_rewrite_redirect {
rewrite ^/test_nginx_rewrite/test_rewrite_redirect$ https://www.baidu.com redirect;
}
}
上述访问流程:
- 请求
http://www.testredirect.com/test_nginx_rewrite/test_rewrite_redirect
。 - Nginx 匹配到
location /test_nginx_rewrite/test_rewrite_redirect
。 rewrite
指令将该请求重定向到https://www.baidu.com
。
这样,用户访问 /test_nginx_rewrite/test_rewrite_redirect
将被重定向到百度的首页。
*2、Rewrite的redirect行为实际应用例子
redirect
标志在 Nginx 的rewrite
指令中用于发出临时重定向响应(HTTP 状态码
302)。以下是一些实际生产应用中的例子:1. 临时重定向到新页面
- 场景: 在维护期间,将用户临时重定向到一个临时维护页面。
- 示例:
server {
listen 80;
server_name example.com;
location / {
rewrite ^/maintenance$ /temporary-maintenance.html redirect;
}
}
这会将访问
/maintenance
的请求临时重定向到/temporary-maintenance.html
,用于临时维护。2. 重定向旧 URL 到新 URL
- 场景: 在网站重构时,临时将旧 URL 重定向到新 URL,以便逐步过渡。
- 示例:
server {
listen 80;
server_name example.com;
location /oldpage {
rewrite ^/oldpage$ /newpage redirect;
}
}
这会将
/oldpage
临时重定向到/newpage
,用于旧 URL 的过渡期。3. 将非 www 请求重定向到 www
- 场景: 临时将非 www 版本的域名重定向到 www 版本。
- 示例:
server {
listen 80;
server_name example.com;
location / {
rewrite ^/(.*)$ http://www.example.com/$1 redirect;
}
}
这会将所有非 www 请求临时重定向到 www 版本的域名,帮助统一网站的 URL 结构。
使用
redirect
标志时,Nginx 会返回一个 HTTP 302 状态码,告诉浏览器临时改变请求的 URL。
3、Rewrite的flag——permanent
在实际生产环境中,使用 Nginx 的
rewrite
指令的permanent
标志(即 301 永久重定向)通常用于以下场景:1. 迁移到新域名
如果你将网站迁移到新域名,你需要将所有旧域名的请求重定向到新域名:
server {
listen 80;
server_name old-domain.com;
location / {
rewrite ^(.*)$ http://new-domain.com$1 permanent;
}
}
在这个配置中,所有请求
old-domain.com
的内容都会被永久重定向到new-domain.com
,保持原有的 URI。2. 将 HTTP 强制重定向到 HTTPS
为了确保所有流量都通过安全的 HTTPS 协议,你可以将 HTTP 请求永久重定向到 HTTPS:
server {
listen 80;
server_name example.com;
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
这里,所有
http://example.com
的请求都会被永久重定向到https://example.com
。3. 规范化 URL 结构
当你更新 URL 结构时,可以使用永久重定向来保持 SEO 排名并避免重复内容问题。例如,将
/old-page
重定向到
/new-page
:
server {
listen 80;
server_name example.com;
location /old-page {
rewrite ^/old-page$ /new-page permanent;
}
}
在这个配置中,访问
example.com/old-page
的用户会被永久重定向到example.com/new-page
。4. 去掉 URL 末尾的斜杠
有时需要去掉 URL 末尾的斜杠以统一 URL 格式:
server {
listen 80;
server_name example.com;
location / {
rewrite ^/(.*)/$ /$1 permanent;
}
}
这里,
example.com/page/
会被永久重定向到example.com/page
。总结
- 301 永久重定向(
permanent
)用于告诉浏览器和搜索引擎请求的 URL 已经改变,并且这种改变是永久的。- 应用场景:更改域名、强制 HTTPS、规范 URL 结构、去掉斜杠等。
这些配置有助于保持用户体验的连续性,并且有助于维护搜索引擎优化(SEO)效果。
4、测试Rewrite的flag——last和break
last
last
标志表示在重写后立即停止处理当前请求,开始新的请求处理流程。这会使 Nginx 在处理请求时终止重写,并重新匹配新的请求。
例子:
server {
listen 80;
location / {
rewrite ^/oldpath/(.*)$ /newpath/$1 last;
}
location /newpath {
# 这里处理 /newpath 的请求
}
}
- 如果请求的是
/oldpath/somefile
,它会被重写为/newpath/somefile
。 - Nginx 会停止重写过程,并开始处理新的
/newpath/somefile
请求。
break
break
标志会终止当前 location
匹配过程,并继续执行 location
块内的其他指令。如果有嵌套的 location
指令,Nginx 不会进一步尝试匹配其他 location
块。
例子:
server {
listen 80;
location / {
rewrite ^/oldpath/(.*)$ /newpath/$1 break;
# 这里可以有其他指令,处理 /newpath 的请求
}
location /newpath {
# 这里处理 /newpath 的请求
}
}
- 如果请求的是
/oldpath/somefile
,Nginx 会将其重写为/newpath/somefile
,并在location /
块内继续处理。 break
确保在重写后不会继续匹配其他location
块,但会处理location /
块中后续的指令。
*4、rewrite的break行为的实际应用例子
在 Nginx 的
rewrite
指令中,break
是一个用于控制 URL 重写流程的指令。使用break
可以停止处理当前location
块中的其他rewrite
规则,并立即执行重写后的请求。在实际生产环境中,
break
常用于以下几种场景:
- 将请求重写到指定路径
假设你有一个应用,它将所有请求重写到一个新的目录中,但在重写后你希望阻止任何进一步的重写操作。下面的配置将所有对
/oldpath
的请求重写为/newpath
,并通过break
指令确保不再进行其他重写操作。
location /oldpath {
rewrite ^/oldpath(.*)$ /newpath$1 break;
}
2. 处理带有查询参数的重写
当你需要将带有特定查询参数的请求重写为另一个路径,但又希望中止进一步的重写操作时,可以使用
break
。例如,将所有带有
?foo=bar
查询参数的请求重写到/special
路径。
location / {
if ($args ~* "foo=bar") {
rewrite ^ /special? break;
}
}
3. 处理静态文件请求
在某些情况下,你可能希望将请求重写为另一个静态文件路径,同时防止任何其他的
rewrite
规则干扰。例如,你想将所有
/images/
目录中的请求重写到一个新的目录/assets/images/
中:
location /images/ {
rewrite ^/images/(.*)$ /assets/images/$1 break;
}
4. 用于 URL 重写和缓存控制
你可能有一个应用需要重写特定的 URL 并添加缓存控制指令。在这种情况下,你可以结合
rewrite
和break
指令来实现。例如,将所有/cache/
的请求重写为/files/
,并且立即结束重写规则处理。
location /cache/ {
rewrite ^/cache/(.*)$ /files/$1 break;
add_header Cache-Control "max-age=3600";
}
总结
在 Nginx 中使用
rewrite
的break
指令可以帮助你控制重写流程,避免进一步的规则干扰,确保请求按照预期进行处理。这种方式对于处理复杂的 URL 重写逻辑尤其有用。
*4、rewrite的last行为的实际应用例子
在 Nginx 的配置中,
rewrite
指令的last
标志用于指示 Nginx 停止当前location
的处理,并继续处理新的location
匹配。在实际生产中,last
标志常用于复杂的 URL
重写和路由场景,以确保请求被正确路由到目标location
。以下是几个实际生产应用中的例子:1. 处理动态内容和重写
假设你有一个网站,所有的请求都应重写到一个 PHP 文件,并传递 URL 中的参数。你可以使用
last
标志确保请求经过适当的处理:
server {
listen 80;
server_name example.com;
location / {
rewrite ^/product/([0-9]+)$ /product.php?id=$1 last;
}
location /product.php {
# 处理 PHP 脚本
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index product.php;
include fastcgi_params;
}
}
在这个配置中,
/product/123
请求会被重写为/product.php?id=123
。last
指示 Nginx 在
rewrite
指令后继续处理新的location
匹配,确保请求被正确传递给 PHP 处理程序。2. 实现带有子目录的 URL 重写
你可能希望将具有特定子目录的 URL 重写到根目录下的处理程序,同时保留子目录信息。例如,将
/blog/2024/post-title
重写为/blog/index.php?year=2024&post=post-title
:
server {
listen 80;
server_name example.com;
location /blog/ {
rewrite ^/blog/([0-9]{4})/(.*)$ /blog/index.php?year=$1&post=$2 last;
}
location /blog/index.php {
# 处理 PHP 脚本
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
在这个配置中,
/blog/2024/post-title
会被重写为
/blog/index.php?year=2024&post=post-title
。last
标志确保 URL 重写后的请求继续在
/blog/index.php
location
中处理。3. 处理和重写 API 路由
对于 API 路由,你可能希望将不同的 API 版本重写到相应的处理程序。例如,将
/api/v1/users
重写到
/api_v1/users_handler
:
server {
listen 80;
server_name api.example.com;
location /api/v1/ {
rewrite ^/api/v1/(.*)$ /api_v1/$1 last;
}
location /api_v1/ {
proxy_pass http://backend_api_v1;
# 其他代理设置
}
}
在这个配置中,所有
/api/v1/
路径的请求会被重写到/api_v1/
路径,并由proxy_pass
指令转发到相应的后端服务。4. URL 重写用于自定义静态文件处理
你可能希望将特定的 URL 请求重写到静态文件目录。例如,将
/static/assets/image.jpg
重写为
/assets/image.jpg
:
server {
listen 80;
server_name example.com;
location /static/ {
rewrite ^/static/(.*)$ /assets/$1 last;
}
location /assets/ {
root /var/www/example.com;
}
}
在这个配置中,
/static/assets/image.jpg
会被重写为/assets/image.jpg
,并从
/var/www/example.com
目录中提供文件。总结
last
标志 用于指示 Nginx 停止当前location
的处理,并重新匹配新的location
配置。- 应用场景:动态内容处理、带子目录的 URL 重写、API 路由处理、自定义静态文件处理等。
这些示例展示了
last
标志在复杂的 URL 重写和路由场景中的实际应用,帮助确保请求被正确处理并路由到目标位置。
*5、Rewrite的实际生产应用配置例子
在实际生产环境中,Nginx 的
rewrite
指令经常用于实现 URL 重写和处理。下面是几个常见的例子及其配置:
1. 将旧 URL 重写为新 URL假设你将一个网站的 URL 结构从
/old-category/old-post
更改为
/new-category/new-post
。你可以使用rewrite
指令将旧 URL 重写为新 URL。
server {
listen 80;
server_name example.com;
location /old-category/old-post {
rewrite ^/old-category/old-post$ /new-category/new-post break;
}
}
这里,
break
指令告诉 Nginx 停止处理当前的location
配置,并将请求转发到新的 URL。2. 将 HTTP 请求重写为 HTTPS
如果你希望强制所有 HTTP 请求都重定向到 HTTPS,可以使用以下配置:
server {
listen 80;
server_name example.com;
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
在这个配置中,所有的 HTTP 请求都会被重定向到相同的 HTTPS URL。
$host
是原始主机名,$request_uri
是请求的 URI。3. 将非 www 请求重写为 www
如果你希望将所有的非 www 请求重定向到带 www 的版本,可以使用以下配置:
server {
listen 80;
server_name example.com;
location / {
rewrite ^/(.*)$ http://www.example.com/$1 permanent;
}
}
这里,所有的
example.com
请求都会被重定向到www.example.com
,保持 URI 不变。4. 重写 URL 以处理动态内容
假设你的应用需要将所有的
/products/123
请求重写为/index.php?product_id=123
:
server {
listen 80;
server_name example.com;
location /products/ {
rewrite ^/products/([0-9]+)$ /index.php?product_id=$1 last;
}
}
这里,
$1
捕获了 URL 中的数字部分,并将其传递给index.php
文件作为查询参数。这些例子展示了 Nginx 的
rewrite
指令在实际生成环境中的应用场景,帮助你处理不同的 URL 结构和请求重定向。
三、HTTPS介绍与Nginx简单配置HTTPS
1、HTTPS的特点及工作原理
使用TLS/SSL协议,对网页内容的传输进行加密传输,相对HTTP更安全;不然容易被攻击,传输该过程数据被窃取或篡改,如:
sub_filter
指令用于在 Nginx 处理响应内容时,对 HTML、CSS 和 JavaScript
内容进行文本替换。例如,你可以用它来替换页面中的某些文本或 URL。此指令通常用于动态内容的内容修改,比如替换某些链接或文本。
sub_filter
指令的示例假设你希望将所有出现的
http://example.com
替换为https://example.com
。配置示例:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
sub_filter 'http://example.com' 'https://example.com';
sub_filter_once off; # 允许替换所有匹配项
}
}
未配置 HTTPS 时篡改网页内容
不配置 HTTPS 意味着网页内容和数据传输是未加密的,可能会受到中间人攻击(MITM)。为了在这种情况下篡改网页内容,可以通过以下方法:
代理服务器:在你的代理服务器(如 Nginx)上使用
sub_filter
指令直接修改响应内容。浏览器扩展:使用某些浏览器扩展(如 Tampermonkey)来在客户端侧修改网页内容。
网络攻击:未经授权的中间人攻击可能会在传输过程中篡改网页内容,但这类行为通常是非法的且不推荐。
HTTPS(HyperText Transfer Protocol Secure)是一种安全的超文本传输协议,旨在保护客户端与服务器之间的数据传输。它是 HTTP 的安全扩展,通过结合使用加密技术来确保数据的机密性、完整性和真实性。
一、HTTPS 的工作原理
加密通信: HTTPS 使用 SSL/TLS(安全套接层/传输层安全)协议来加密客户端和服务器之间的通信。加密保证了数据在传输过程中不会被未授权的第三方读取或篡改。
身份验证: HTTPS 使用数字证书来验证服务器的身份。这确保了客户端连接到的是合法的服务器,而不是一个伪装的恶意服务器。
数据完整性: 通过使用加密和哈希函数,HTTPS 保障数据在传输过程中不会被修改。
二、HTTPS 使用证书的原理
证书颁发机构(CA): 证书是由受信任的第三方组织——证书颁发机构(CA)颁发的。CA 验证服务器的身份,并签发证书来证明服务器的合法性。
证书内容:
- 公钥: 用于加密数据的公钥。
- 私钥: 仅服务器持有,用于解密数据和数字签名。
- 证书签名: 由 CA 使用其私钥对证书进行签名,确保证书的真实性。
- 域名信息: 证书中包含与证书相关的域名或子域名。
- CA 信息: 颁发证书的 CA 的信息。
HTTPS 握手过程:
- 客户端发起请求: 客户端向服务器发起 HTTPS 请求,服务器响应并发送其 SSL/TLS 证书。
- 证书验证: 客户端验证服务器的证书是否由受信任的 CA 颁发,证书是否过期,域名是否匹配。
- 密钥交换: 客户端和服务器通过公钥加密技术交换加密密钥。客户端生成一个随机密钥(对称密钥),用服务器的公钥加密并发送给服务器。服务器使用其私钥解密这个密钥。
- 加密通信: 双方使用共享的对称密钥来加密后续的数据传输,确保数据在传输过程中的安全性。
HTTPS 的好处
- 数据加密: 保护数据在网络传输中的隐私。
- 身份验证: 确保用户连接到的是合法的服务器。
- 数据完整性: 防止数据在传输过程中被篡改。
通过以上这些机制,HTTPS 提供了比 HTTP 更高的安全性和隐私保护。
2、HTTPS的证书类型
HTTPS 证书用于加密客户端与服务器之间的通信,并确保数据的安全性。根据用途和认证程度,HTTPS 证书可以分为几种不同的类型。以下是不同 HTTPS 证书类型的表格概述:
证书类型 | 说明 | 验证方式 | 适用场景 |
---|---|---|---|
域名验证证书 (DV) | 仅验证域名的所有权。获取过程相对简单快速,通常只需通过电子邮件验证或在网站上添加指定文件。 | 自动化域名验证,通常通过邮件或文件验证。 | 适合个人网站、小型网站、博客等。 |
组织验证证书 (OV) | 验证域名所有权和企业/组织的合法性。需要提供更多的公司信息和证明材料。 | 需要提交组织的法律文件、公司注册信息等。 | 适合中小型企业、商业网站。 |
扩展验证证书 (EV) | 提供最高级别的验证,验证企业的合法性、运营状态和法律身份。浏览器地址栏通常会显示公司名称。 | 需要详细的法律和运营证明,包括公司的法人文件等。 | 适合大型企业、金融机构、电子商务网站。 |
通配符证书 (Wildcard) | 允许一个证书保护一个域名及其所有子域名。例如,*.example.com 可以保护 www.example.com 和 blog.example.com 。 | 与 DV 或 OV 证书相同,只是覆盖了子域名。 | 适合需要管理多个子域名的网站。 |
多域名证书 (SAN) | 允许一个证书保护多个不同的域名或子域名。例如,可以同时保护 example.com 、example.net 和 example.org 。 | 需要提供所有需要保护的域名,可能包括验证所有域名。 | 适合需要保护多个不同域名的网站。 |
统一通讯证书 (UCC) | 最初设计用于 Microsoft Exchange 和 Office Communications Server,但现在也用于一般的多域名保护。 | 通常与 SAN 证书类似,验证所有列出的域名。 | 适合企业环境中需要保护多个域名的场景。 |
证书类型的选择依据
- DV 证书:适用于个人和非商业网站,成本低,验证过程快。
- OV 证书:适用于需要中等级别信任的网站,如中小企业的网站,提供了更多的验证和信任。
- EV 证书:适用于对安全性有高要求的网站,如金融服务网站、电子商务平台,提供最高级别的验证。
- 通配符证书:适用于需要保护大量子域名的网站,简化了证书管理。
- 多域名证书:适用于需要保护多个不同域名的网站,可以减少管理和维护证书的复杂度。
- UCC 证书:适用于企业和商业环境中需要保护多个域名的场景。
3、Nginx简单测试配置HTTPS
(生产中不使用,仅供自行测试,生成)
1)生成HTTPS证书文件、密钥文件
openssl genrsa -idea -out website_name.key
openssl req -days 36500 -x509 -sha256 -nodes -newkey rsa:2048 -keyout website_name.key -out website_name.crt
2)编写Nginx配置文件
server{
...
server_name https://域名或ip; ?????
rewrite ^(.*)$ https://域名或ip; ?????
listen 443 ssl;
ssl_certificate 上面的website_name.crt的路径;
ssl_certificate_key 上面的website_name.key的路径;
...
}
注:
错误配置:
server{
listen 443 ssl;
server_name www.testhttps.com;
root /code;
index index.html;
ssl_certificate conf.d/website_name.crt;
ssl_certificate_key conf.d/website_name.key;
rewrite ^(.*)$ https://www.testhttps.com permanent;
}
你的 Nginx 配置片段中,有一个关键的配置错误。下面是具体的问题以及如何修正它:
主要问题
重定向配置的问题: 在配置 HTTPS 的服务器块中,你使用了
rewrite
指令进行重定向。rewrite
指令的目的是为了在 URL 匹配时进行重写或重定向。你的配置中,rewrite
指令将所有请求重定向到
https://www.testhttps.com
。然而,你的服务器块已经监听了 HTTPS(端口443),所以这种重定向是多余的。如果你希望将 HTTP 请求重定向到 HTTPS,应该在监听 HTTP 的服务器块中进行配置。SSL/TLS 配置的最佳实践: 你还需要配置其他 SSL/TLS 的相关设置,如
ssl_protocols
和ssl_ciphers
,以确保你的网站具有良好的安全性。这是为了强制使用现代的加密协议和密码套件来保护数据。修正建议
- 如果你需要将 HTTP 请求重定向到 HTTPS,应该在另一个服务器块中处理 HTTP 请求,例如:
```nginx
server {
listen 80;
server_name www.testhttps.com;
return 301 https://$host$request_uri;
}
```
这将把所有 HTTP 请求重定向到 HTTPS。 2. **配置 HTTPS 服务器块时,确保包括基本的 SSL/TLS 配置**:
```nginx
server {
listen 443 ssl;
server_name www.testhttps.com;
root /code;
index index.html;
ssl_certificate conf.d/website_name.crt;
ssl_certificate_key conf.d/website_name.key;
# 推荐配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!MD5:!SSLv3';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 其他配置(如 gzip、日志等)
access_log /var/log/nginx/your_access_log.log;
error_log /var/log/nginx/your_error_log.log;
# 页面根目录
root /code;
index index.html;
}
```
总结
你的配置中最主要的问题是错误地使用了
rewrite
指令来进行重定向,而正确的做法是在 HTTP
服务器块中进行重定向。同时,也需要确保 HTTPS 服务器块中的 SSL/TLS 配置是完整和安全的。
测试结果:
4、集群、反向代理环境下简单配置测试HTTPS
如何配置:
负载均衡服务器存放含有同一域名Web应用的Web服务器的证书文件
为了配置使得用户通过 HTTPS 访问你的负载均衡服务器,同时两台 Web 应用服务器都使用相同的 HTTPS证书文件和密钥文件存放在负载均衡服务器上,你可以按照以下步骤操作:
一、1. 负载均衡服务器 Nginx 配置
负载均衡服务器需要处理 HTTPS 请求,并将流量代理到后台的 Web 应用服务器。你需要在负载均衡服务器上配置 Nginx,以支持
HTTPS,并设置好代理功能。Nginx 配置示例(负载均衡服务器):
安装 Nginx 和生成 SSL 证书
- 确保你的 SSL 证书(例如
fullchain.pem
)和私钥(例如privkey.pem
)已经存放在负载均衡服务器上。编辑负载均衡服务器的 Nginx 配置文件(通常在
/etc/nginx/nginx.conf
或/etc/nginx/sites-available/default
):
server {
listen 443 ssl;
server_name yourdomain.com; # 替换为你的域名
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://backend; # 代理到名为 backend 的 upstream
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
upstream backend {
server webserver1.example.com; # 替换为 Web 服务器的内部地址
server webserver2.example.com; # 替换为 Web 服务器的内部地址
}
ssl_certificate
和ssl_certificate_key
指定了 SSL 证书的位置。proxy_pass
将请求转发到 Web 应用服务器。upstream backend
定义了负载均衡的 Web 服务器列表。二、Web 应用服务器 Nginx 配置
在 Web 应用服务器上,你只需配置 Nginx 处理 HTTP 请求,因为 HTTPS 连接已经由负载均衡服务器处理。
Nginx 配置示例(Web 应用服务器):
- 编辑 Web 应用服务器的 Nginx 配置文件(通常在
/etc/nginx/nginx.conf
或/etc/nginx/sites-available/default
):
server {
listen 80;
server_name webserver1.example.com; # 替换为 Web 服务器的内部地址
location / {
root /path/to/your/application; # 替换为你的应用程序路径
index index.html;
}
}
listen 80;
指定 Web 应用服务器只监听 HTTP 请求。- 配置适当的
root
和index
指令以处理请求。三. 证书与密钥文件是否相同的配置
- 证书和密钥文件的配置
证书和密钥文件是否可以相同:
- 相同证书和密钥:在负载均衡服务器上配置证书和私钥,然后在 Web 应用服务器上可以不配置任何证书。这样做的好处是简化配置和证书管理。
- 不同证书和密钥:如果你想要每台 Web 应用服务器上配置不同的证书和私钥,通常这会增加复杂性,因为你需要为每台服务器单独配置 HTTPS。此时,每台 Web 应用服务器的 Nginx 配置会包括 SSL 证书和私钥。
- 配置不同证书和密钥(如果需要)
如果你决定配置不同的证书和密钥,下面是 Web 应用服务器的配置示例:
Nginx 配置文件(Web 应用服务器,使用不同的证书和密钥):
server {
listen 443 ssl;
server_name webserver1.internal; # 替换为 Web 服务器的内部地址
ssl_certificate /etc/nginx/ssl/webserver1/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/webserver1/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /path/to/your/application; # 替换为你的应用程序路径
index index.html;
}
}
- 在这种情况下,Web 应用服务器将处理 HTTPS 请求,所以需要配置
ssl_certificate
和ssl_certificate_key
。四. 其他注意事项
- 确保防火墙设置:确保负载均衡服务器的 443 端口对外开放,而 Web 应用服务器的 80 端口对负载均衡服务器开放。
- 重启 Nginx:在修改配置文件后,重启 Nginx 服务以使配置生效:
sudo systemctl restart nginx
- 测试配置:通过浏览器访问你的域名,检查 HTTPS 是否正常工作,并确保负载均衡器正确地将请求分发到 Web 应用服务器。
注:
1、HTTPS的证书和密钥是基于域名的吗?什么时候证书和密钥是相同的?什么时候证书和密钥是不同的?
HTTPS 的证书和密钥确实是基于域名的。这里是详细说明:
基于域名的证书和密钥:
- 证书:为特定域名(如
example.com
)颁发,验证该域名的所有权和安全性。- 密钥:与证书配对使用,保证数据加密和解密的安全。
证书和密钥相同的情况:
- 单一域名:一个证书和私钥用于一个域名(如
www.example.com
),通常由负载均衡器或单一服务器使用。- 通配符证书:一个证书(如
*.example.com
)适用于该域名下的所有子域名,密钥与证书是配套的。证书和密钥不同的情况:
- 多个域名:不同的域名(如
example.com
和example.org
)需要不同的证书和密钥。- 不同的服务:在不同的服务器上使用不同证书和密钥,可能是为了安全隔离或管理方便。
通常,证书和密钥都是配对使用的,并且在一个环境中它们是相同的。
测试:
1、两台Web服务器配置:
2、负载均衡服务器的配置:
3、测试效果:
解释:“在 Web 应用服务器上,你只需配置 Nginx 处理 HTTP 请求,因为 HTTPS 连接已经由负载均衡服务器处理”
这意味着Web 应用服务器只需要处理解密后的 HTTP 请求,而不需要处理加密的 HTTPS 连接。负载均衡器负责完成 HTTPS
加密和解密工作,将加密的 HTTPS 请求转换为明文的 HTTP 请求,并将这些 HTTP 请求转发给 Web 应用服务器。这样,Web
应用服务器只需关注应用逻辑和内容处理,而无需额外配置 HTTPS 或管理 SSL/TLS 证书。这种配置简化了服务器设置,提升了性能和安全性
注:如果Web服务器需要接受负载均衡服务器的HTTPS时,将使用如下配置:
确保后端服务器的 nginx 或其他 Web 服务器配置接受 HTTPS 请求(即,后端服务器需要配置
SSL/TLS)。如果后端服务器仅接受 HTTP 请求,proxy_pass 应该配置为 http://backend 而不是
https://backend。
- Web服务器的配置:
- 负载均衡服务器的配置:
注:负载均衡服务器配置了 HTTPS 的情况下,负载均衡服务器与后端服务器之间的通信是否需要使用 HTTPS?
在负载均衡服务器配置了 HTTPS 的情况下,负载均衡服务器与后端服务器之间的通信是否需要使用HTTPS,取决于你的安全需求和架构设计。下面是一些常见的配置选项及其影响:
一. 前端 HTTPS 到负载均衡服务器,后端 HTTP
- 前端(客户端到负载均衡服务器): 使用 HTTPS 加密。
- 后端(负载均衡服务器到真实服务器): 使用 HTTP 明文传输。
优点:
- 简化配置: 后端服务器配置更简单,因为不需要处理 HTTPS 证书和加密操作。
- 性能: 负载均衡服务器处理 HTTPS 证书和加密/解密操作,从而减轻了后端服务器的负担。
缺点:
- 数据安全性: 数据在负载均衡服务器和后端服务器之间传输是明文的,这可能会带来安全风险。如果你的网络环境不受信任或不安全,这可能导致数据泄露。
适用场景:
- 内部网络中,负载均衡器和后端服务器位于受信任的环境中。
- 性能和简单性优先于最高级别的安全性。
二. 前端 HTTPS 到负载均衡服务器,后端 HTTPS
- 前端(客户端到负载均衡服务器): 使用 HTTPS 加密。
- 后端(负载均衡服务器到真实服务器): 使用 HTTPS 加密。
优点:
- 完整的数据加密: 数据在整个传输链路中都被加密,从客户端到后端服务器,确保数据在传输过程中不被窃取或篡改。
- 符合高安全需求的场景: 确保即使负载均衡器与后端服务器之间的通信被监听,也无法解密数据。
缺点:
- 性能开销: 负载均衡服务器和后端服务器都需要处理 HTTPS 加密和解密,可能会增加系统开销。
- 配置复杂性: 后端服务器需要处理 HTTPS 配置,包括证书管理。
适用场景:
- 高安全性要求的环境,如处理敏感数据或法规要求保护数据传输的场景。
- 负载均衡器和后端服务器位于不受信任或公共网络中。
三. 前端 HTTP 到负载均衡服务器,后端 HTTPS
- 前端(客户端到负载均衡服务器): 使用 HTTP 明文传输。
- 后端(负载均衡服务器到真实服务器): 使用 HTTPS 加密。
优点:
- 减少客户端的复杂性: 客户端与负载均衡器之间的配置更简单,因为不需要处理 HTTPS。
缺点:
- 数据安全性: 客户端到负载均衡器的数据是明文的,可能会被中间人攻击窃取。
适用场景:
- 内部系统中,要求负载均衡器与后端服务器之间有加密,但不要求客户端与负载均衡器之间的通信加密。
四. 总结
选择最适合的配置取决于你的安全需求、性能要求和架构设计。如果你的网络环境不受信任,或者你处理的是敏感数据,建议在负载均衡服务器和后端服务器之间也使用HTTPS。否则,可以选择前端 HTTPS 到负载均衡服务器,而后端 HTTP 的配置来简化部署和提高性能。