介绍
Apache 的mod_rewrite
模块允许您以更简洁的方式重写 URL,将人类可读的路径转换为代码友好的查询字符串。它还允许您根据条件重写 URL。
一个.htaccess
文件,您可以创建并应用重写规则,而无需访问服务器配置文件。通过将.htaccess
文件放在网站的根目录中,您可以在每个站点或每个目录的基础上管理重写。
在本教程中,您将启用mod_rewrite
并使用.htaccess
文件来创建基本的 URL 重定向,然后探索几个高级用例。
先决条件
要学习本教程,您需要:
-
按照Ubuntu 18.04 初始服务器设置指南设置一台 Ubuntu 18.04 服务器。这包括一个 sudo 非 root 用户和一个防火墙。
-
按照如何在 Ubuntu 18.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈的步骤 1 安装 Apache。
步骤 1 — 启用 mod_rewrite
为了让 Apache 理解重写规则,我们首先需要激活mod_rewrite
. 它已安装,但在默认 Apache 安装中被禁用。使用a2enmod
命令启用模块:
- sudo a2enmod rewrite
这将激活模块或提醒您该模块已启用。要使这些更改生效,请重新启动 Apache。
- sudo systemctl restart apache2
mod_rewrite
现在已完全启用。在下一步中,我们将设置一个.htaccess
文件,用于定义重定向的重写规则。
步骤 2 — 设置 .htaccess
一个.htaccess
文件,允许我们修改我们的重写规则,而无需访问服务器配置文件。因此,.htaccess
对于您的 Web 应用程序的安全性至关重要。文件名前面的句点确保文件被隐藏。
注意:您可以放入.htaccess
文件的任何规则也可以直接放入服务器配置文件中。事实上,官方 Apache 文档建议使用服务器配置文件,而不是.htaccess
因为 Apache 以这种方式处理它的速度更快。
然而,在这个简单的例子中,性能提升可以忽略不计。此外,设置规则.htaccess
很方便,尤其是在同一服务器上有多个网站时。它不需要重新启动服务器即可使更改生效,并且不需要 root 权限来编辑这些规则,从而简化了维护并使非特权帐户的更改成为可能。一些流行的开源软件,如 WordPress 和 Joomla,通常依赖于.htaccess
软件的文件来按需修改和创建其他规则。
在开始使用.htaccess
文件之前,您需要设置并保护一些其他设置。
默认情况下,Apache 禁止使用.htaccess
文件来应用重写规则,因此首先您需要允许对文件进行更改。使用nano
或您喜欢的文本编辑器打开默认的 Apache 配置文件。
- sudo nano /etc/apache2/sites-available/000-default.conf
在该文件中,您会发现<VirtualHost *:80>
从第一行开始的块。在该块内,添加以下新块,使您的配置文件如下所示。确保所有块都正确缩进。
<VirtualHost *:80>
<Directory /var/www/html>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
. . .
</VirtualHost>
保存并关闭文件。要使这些更改生效,请重新启动 Apache。
- sudo systemctl restart apache2
现在,.htaccess
在 Web 根目录中创建一个文件。
- sudo nano /var/www/html/.htaccess
在新文件的顶部添加这一行以激活重写引擎。
RewriteEngine on
保存文件并退出。
您现在拥有一个.htaccess
可用于管理 Web 应用程序路由规则的操作文件。在下一步中,我们将创建示例网站文件,用于演示重写规则。
第 3 步 – 配置 URL 重写
在这里,我们将设置一个基本的 URL 重写,它将漂亮的 URL 转换为页面的实际路径。具体来说,我们将允许用户访问,但会显示一个名为 的页面。http://your_server_ip/about
about.html
首先创建一个about.html
在 Web 根目录中命名的文件。
- sudo nano /var/www/html/about.html
将以下 HTML 代码复制到文件中,然后保存并关闭它。
<html>
<head>
<title>About Us</title>
</head>
<body>
<h1>About Us</h1>
</body>
</html>
您可以在 访问此页面,但请注意,如果您尝试访问,您将看到404 Not Found错误。为了访问页面,我们将创建一个重写规则。http://your_server_ip/about.html
http://your_server_ip/about
/about
都RewriteRules
遵循这个格式:
RewriteRule pattern substitution [flags]
RewriteRule
指定指令。pattern
是一个正则表达式,它与 URL 中的所需字符串相匹配,这是查看者在浏览器中键入的内容。substitution
是实际 URL 的路径,即文件 Apache 服务器的路径。flags
是可选参数,可以修改规则的工作方式。
让我们创建我们的 URL 重写规则。打开.htaccess
文件。
- sudo nano /var/www/html/.htaccess
在第一行之后,添加RewriteRule
红色标记并保存文件。
RewriteEngine on
RewriteRule ^about$ about.html [NC]
在这种情况下,^about$
是模式,about.html
是替代,[NC]
是标志。我们的示例使用了几个具有特殊含义的字符:
^
表示 URL 的开始,在 之后your_server_ip/
。$
表示 URL 的结尾。about
匹配字符串“about”。about.html
是用户访问的实际文件。[NC]
是使规则不区分大小写的标志。
您现在可以在浏览器中访问。事实上,根据上面显示的规则,以下 URL 将指向:http://your_server_ip/about
about.html
http://your_server_ip/about
,因为规则定义。http://your_server_ip/About
,因为规则不区分大小写。http://your_server_ip/about.html
,因为原始的正确文件名将始终有效。
但是,以下操作不起作用:
http://your_server_ip/about/
,因为规则明确规定在 之后可能没有任何东西about
,因为$
字符出现在 之后about
。http://your_server_ip/contact
,因为它不会匹配about
规则中的字符串。
您现在拥有一个.htaccess
带有基本规则的操作文件,您可以根据需要修改和扩展该规则。在以下部分中,我们将展示两个常用指令的附加示例。
示例 1 – 使用 RewriteRule 简化查询字符串
Web 应用程序通常使用查询字符串,这些字符串使用?
地址后的问号 ( )附加到 URL 。单独的参数使用与号 ( &
)分隔。查询字符串可用于在各个应用程序页面之间传递附加数据。
例如,用 PHP 编写的搜索结果页面可能使用类似http://example.com/results.php?item=shirt&season=summer
. 在此示例中,将两个附加参数传递给假想的result.php
应用程序脚本:item
,值为shirt
,以及season
值为 summer
。应用程序可以使用查询字符串信息为访问者构建正确的页面。
Apache 重写规则通常用于将上述这些长而令人不快的链接简化为更易于键入和直观解释的友好 URL。在这个例子中,我们想将上面的链接简化为http://example.com/shirt/summer
. 在shirt
和summer
参数值仍然在地址,但没有查询字符串和脚本名称。
这是实现这一点的一条规则:
RewriteRule ^shirt/summer$ results.php?item=shirt&season=summer [QSA]
在shirt/summer
明确的请求的地址匹配和Apache被告知以服务results.php?item=shirt&season=summer
代替。
这些[QSA]
标志通常用于重写规则。它们告诉 Apache 将任何额外的查询字符串附加到所提供的 URL,因此如果访问者键入,服务器将以. 没有它,额外的查询字符串将被丢弃。http://example.com/shirt/summer?page=2
results.php?item=shirt&season=summer&page=2
虽然此方法达到了预期的效果,但项目名称和季节都被硬编码到规则中。这意味着该规则不适用于任何其他项目,例如pants
,或季节,例如winter
。
为了使规则更通用,我们可以使用正则表达式来匹配原始地址的部分并在替换模式中使用这些部分。修改后的规则将如下所示:
RewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2 [QSA]
括号中的第一个正则表达式组匹配包含字母数字字符和数字的字符串,例如shirt
orpants
并将匹配的片段保存为$1
变量。括号中的第二个正则表达式组与summer
、winter
、fall
、 或完全匹配spring
,并类似地将匹配的片段另存为$2
。
然后将匹配的片段用于结果 URLitem
和season
变量中,而不是我们之前使用的硬编码shirt
和summer
值。
例如,上面将转换http://example.com/pants/summer
为http://example.com/results.php?item=pants&season=summer
. 这个例子也是面向未来的,允许使用单个规则正确重写多个项目和季节。
示例 2 – 使用 RewriteConds 添加逻辑条件
重写规则不一定总是没有任何限制地一一评估。该RewriteCond
指令允许我们向重写规则添加条件以控制何时处理规则。全部RewriteConds
遵循以下格式:
RewriteCond TestString Condition [Flags]
RewriteCond
指定RewriteCond
指令。TestString
是要测试的字符串。Condition
是要匹配的模式或条件。Flags
是可以修改条件和评估规则的可选参数。
如果 a 的RewriteCond
计算结果为真,RewriteRule
则将考虑紧随其后的情况。如果不是,则规则将被丢弃。MultipleRewriteCond
可以一个接一个地使用,并且在默认行为下,所有必须评估为 true 才能考虑以下规则。
例如,假设您希望将所有对站点上不存在的文件或目录的请求重定向回主页,而不是显示标准的404 Not Found错误页面。这可以通过以下条件规则来实现:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /
有了以上:
%{REQUEST_FILENAME}
是要检查的字符串。在这种情况下,它是请求的文件名,它是每个请求都可用的系统变量。-f
是一个内置条件,用于验证请求的名称是否存在于磁盘上并且是一个文件。该!
是否定操作。组合,!-f
仅当指定名称不存在或不是文件时才计算为真。- 同样,
!-d
仅当指定的名称不存在或不是目录时才计算为真。
在RewriteRule
最终线将生效只为请求不存在的文件或目录。它RewriteRule
本身非常简单,并将每个请求重定向到/
网站根目录。
结论
mod_rewrite
允许您创建人类可读的 URL。在本教程中,您学习了如何使用RewriteRule
指令重定向 URL,包括带有查询字符串的 URL。您还学习了如何使用RewriteCond
指令有条件地重定向 URL 。
如果您想了解更多关于mod_rewrite
,请查看Apache 的 mod_rewrite 介绍和Apache 的 mod_rewrite 官方文档。