介绍
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
对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
现在,在Web根目录中创建一个.htaccess
文件。
sudo nano /var/www/html/.htaccess
在新文件的顶部添加此行以激活重写引擎。
RewriteEngine on
保存文件并退出。
您现在有一个可操作的.htaccess
文件,可用于管理Web应用程序的路由规则。 在下一步中,我们将创建示例网站文件,我们将使用它们来演示重写规则。
第3步 - 配置URL重写
在这里,我们将设置一个基本的URL重写,将漂亮的URL转换为实际的页面路径。 具体来说,我们将允许用户访问http:// your_server_ip /about
,但会显示名为about.html
的页面。
首先在Web根目录中创建名为about.html
的文件。
sudo nano /var/www/html/about.html
将以下HTML代码复制到该文件中,然后保存并关闭它。
<html>
<head>
<title>About Us</title>
</head>
<body>
<h1>About Us</h1>
</body>
</html>
您可以通过http:// your_server_ip /about.html
访问此页面,但请注意,如果您尝试访问http:// your_server_ip /about
,您将看到404 Not Found错误。 要使用/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]
是标志。 我们的示例使用了一些具有特殊含义的字符:
-
^
表示在your_server_ip /
之后的URL的开头。 -
$
表示URL的结尾。 -
about
匹配字符串“约”。 -
about.html
是用户访问的实际文件。 -
[NC]
是一个使规则不区分大小写的标志。
您现在可以在浏览器中访问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
,因为$
字符出现在about
之后。 -
http:// your_server_ip /contact
,因为它与规则中的about
字符串不匹配。
您现在拥有一个可操作的.htaccess
文件,其中包含一条基本规则,您可以根据需要进行修改和扩展。 在以下部分中,我们将展示常用指令的另外两个示例。
示例1 - 使用RewriteRule简化查询字符串
Web应用程序通常使用查询字符串 ,这些字符串在地址后使用问号( ?
)附加到URL。 使用和号( &
)分隔单独的参数。 查询字符串可用于在各个应用程序页面之间传递附加数据。
例如,用PHP编写的搜索结果页面可能使用http://example.com/results.php?item=shirt&season=summer
URL。 在此示例中,将两个附加参数传递给虚构的result.php
应用程序脚本: item
,值为shirt
, season
为值summer
。 应用程序可以使用查询字符串信息为访问者构建正确的页面。
Apache重写规则通常用于将如上所述的长而不愉快的链接简化为友好的URL ,这些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
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
或pants
等数字的字符串,并将匹配的片段保存为$1
变量。 括号中的第二个常规rexpression组恰好与summer
, winter
, fall
或spring
匹配,同样将匹配的片段保存为$2
。
然后将匹配的片段用于item
和season
变量中的结果URL,而不是之前使用的硬编码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
是可选参数,可以修改条件和评估规则。
如果RewriteCond
计算结果为true,则会考虑紧随其后的RewriteRule
。 如果不相关,则该规则将被丢弃。 可以一个接一个地使用多个RewriteCond
,并且在默认行为的情况下,所有必须评估为true以便考虑以下规则。
例如,假设您希望将所有请求重定向到您站点上不存在的文件或目录,并将其重定向到主页,而不是显示标准的404 Not Found错误页面。 这可以通过以下条件规则来实现:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /
有了上述:
-
%{REQUEST_FILENAME}
是要检查的字符串。 在这种情况下,它是请求的文件名,它是可用于每个请求的系统变量。 -
-f
是内置条件,用于验证所请求的名称是否存在于磁盘上且是文件。 的!
是一个否定运算符。 组合,!-f
仅在指定的名称不存在或不是文件时才计算为true。 - 类似地,仅当指定的名称不存在或不是目录时,
!-d
才会计算为true。
最后一行的RewriteRule
仅对不存在的文件或目录的请求生效。 RewriteRule
本身非常简单,并将每个请求重定向到/
website root。
结论
mod_rewrite
允许您创建人类可读的URL。 在本教程中,您学习了如何使用RewriteRule
指令重定向URL,包括具有查询字符串的URL。 您还学习了如何使用RewriteCond
指令有条件地重定向URL。
如果您想了解有关mod_rewrite
更多信息,请查看Apache的mod_rewrite简介和Apache的mod_rewrite官方文档 。