在CentOS 7上设置Apache的mod_rewrite的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
简介
Apache 是一个模块化的 Web 服务器,允许您通过启用和禁用模块来定制其功能。这为管理员提供了定制 Apache 功能以满足其 Web 应用程序需求的能力。
在本教程中,我们将在 CentOS 7 服务器上安装 Apache,确认 mod_rewrite
模块已启用,并探索一些基本功能。
先决条件
在按照本教程操作之前,请确保您拥有一个具有 sudo 权限的常规非 root 用户。您可以从我们的指南《如何在 CentOS 上创建一个 Sudo 用户》中了解如何设置具有这些权限的用户。
步骤 1 – 安装 Apache
我们将使用 CentOS 的默认软件包管理实用程序 yum
来安装 Apache。
sudo yum install httpd
在出现 Is this ok [y/d/N]:
提示时,输入 Y
并按 ENTER
键授权安装。
接下来,使用 systemctl
实用程序启动 Apache 守护进程,它是一个独立的进程,创建一个子进程或线程池来处理请求:
sudo systemctl start httpd
要确保 Apache 成功启动,请使用 status
命令检查其状态:
sudo systemctl status httpd
. . .
systemd[1]: Starting The Apache HTTP Server...
systemd[1]: Started The Apache HTTP Server.
Apache 已经启动运行,现在让我们转向它的模块。
步骤 2 – 验证 mod_rewrite
在 CentOS 7 版本中,默认情况下启用了 mod_rewrite
Apache 模块。我们将使用 httpd
命令和 -M
标志来验证这一点,该标志打印出所有已加载模块的列表:
httpd -M
. . .
remoteip_module (shared)
reqtimeout_module (shared)
rewrite_module (shared)
setenvif_module (shared)
slotmem_plain_module (shared)
. . .
如果输出中没有出现 rewrite_module
,则通过使用 vi
编辑器编辑 00-base.conf
文件来启用它:
sudo vi /etc/httpd/conf.modules.d/00-base.conf
一旦文本文件打开,输入 i
进入插入模式,然后添加或取消下面突出显示的行:
#
# This file loads most of the modules included with the Apache HTTP
# Server itself.
#
. . .
LoadModule rewrite_module modules/mod_rewrite.so
. . .
现在按 ESC
退出插入模式。然后,输入 :x
然后按 ENTER
键保存并退出文件。
接下来,通过重新启动 Apache 应用配置更改:
sudo systemctl restart httpd
安装了 Apache 并启用了 mod_rewrite
模块后,我们可以配置使用 .htaccess
文件。
步骤 3 – 设置 .htaccess 文件
.htaccess
文件允许在不更改服务器配置文件的情况下,在每个域的基础上定义 Apache 指令,包括 RewriteRule
。在 Linux 中,以点(.
)开头的文件被视为隐藏文件。
在使用 .htaccess
文件之前,我们需要更新 AllowOverride
设置以允许覆盖 Apache 指令。
sudo vi /etc/httpd/conf/httpd.conf
找到 <Directory /var/www/html>
部分,并将 AllowOverride
指令从 None
更改为 All
:
. . .
<Directory /var/www/html>
. . .
#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
#
AllowOverride All
. . .
</Directory>
. . .
保存并退出文件,然后重新启动 Apache 以应用更改:
sudo systemctl restart httpd
接下来,在 Apache 的默认文档根目录 /var/www/html
中创建一个 .htaccess
文件。
sudo vi /var/www/html/.htaccess
在文件顶部添加以下行以激活 RewriteEngine
,指示 Apache 处理后续的任何规则:
RewriteEngine On
保存并退出文件。
现在您有了一个 .htaccess
文件,可以在其中定义规则以根据需要操作 URL。在我们开始编写实际规则之前,让我们花一点时间来回顾基本的 mod_rewrite
语法。
步骤 4 – 探索 RewriteRule 语法
RewriteRule
指令允许我们基于 URL 重新映射请求到 Apache。一个 .htaccess
文件可以包含多个重写规则,但在运行时,Apache 会按照它们定义的顺序应用规则。重写规则由以下结构组成:
RewriteRule Pattern Substitution [Flags]
- RewriteRule:指定
RewriteRule
指令 - Pattern:匹配所需字符串的 PCRE(Perl 兼容正则表达式)。您可以在这里了解更多关于正则表达式的信息。
- Substitution:匹配请求应该发送到的位置
- [Flags]:修改规则的可选参数。有关可用标志及其含义的更多信息,请参阅 Apache 的 Rewrite Flags 文档。
RewriteRule
是 mod_rewrite
指令的主要工具,这就是为什么我们在本教程中主要关注它。
步骤 5 – 探索 RewriteCond 语法
RewriteCond
指令允许我们向重写规则添加条件。重写条件由以下结构组成:
RewriteCond TestString Condition [Flags]
- RewriteCond:指定
RewriteCond
指令 - TestString:要测试的字符串
- Condition:要匹配的模式
- [Flags]:可选参数,用于修改条件。
RewriteCond
指令不允许 Apache 考虑其后的任何重写规则,除非特定条件计算为真。
步骤 6 – 设置文件
我们将设置一个基本的重写规则,允许用户在 Web 浏览器的地址栏中访问 about.html
页面而无需输入文件扩展名(.html
)。首先,在文档根目录中创建一个 about.html
文件:
sudo vi /var/www/html/about.html
将以下 HTML 代码复制到文件中:
<!DOCTYPE html>
<html>
<head>
<title>About Us</title>
</head>
<body>
<h1>About Us</h1>
</body>
</html>
保存并退出文件。
在 Web 浏览器中,导航至以下地址:
http://server_domain_or_IP/about.html
您应该会看到一个白色页面上面写着 About Us。如果您从地址栏中移除 .html 并重新加载页面,您将收到一个 404 Not Found 错误。Apache 只能通过完整文件名访问组件,但我们可以通过重写规则来改变这一点。
步骤 7 – 设置 RewriteRule
我们希望访问 About Us 页面的访问者无需输入 .html
。为实现这一点,我们将创建一个规则。
打开 .htaccess
文件:
sudo vi /var/www/html/.htaccess
在 RewriteEngine On
行之后,添加以下内容:
RewriteRule ^about$ about.html [NC]
保存并退出文件。
访问者现在可以使用 http://server_domain_or_IP/about
URL 访问 About Us 页面。
让我们来检查一下重写规则:
^about$
用作从 URL 中匹配的模式,以及用户在其浏览器中输入的内容。
我们的示例使用了一些 元字符 来确保该术语仅存在于 URL 的特定位置:
^
表示 URL 的开始,在server_domain_or_IP/
之后被剥离。$
表示 URL 的结束。
about.html
显示了 Apache 在遇到匹配模式时提供的文件路径。
[NC]
是一个标志,指示重写规则不区分大小写,以便用户可以在 URL 中输入大小写字母。例如,以下 URL 指向 about.html
文件:
- server_domain_or_IP/about
- server_domain_or_IP/About
- server_domain_or_IP/ABOUT
通过一个简单的重写规则,我们为用户访问 About Us 页面增加了动态方面。
常见模式
现在我们对重写规则有了基本的了解,我们将在本节中探索另外两个示例。
示例文件可以设置,但本教程不包括创建它们;仅包括重写规则本身。
示例 1:使用 RewriteRule 简化查询字符串
Web 应用程序通常使用查询字符串,该查询字符串使用问号字符(?
)附加到 URL,并由和号字符(&
)分隔。Apache 在匹配重写规则时会忽略这两个字符。然而,有时可能需要查询字符串以在页面之间传递数据。例如,使用 PHP 编写的搜索结果页面的 URL 可能如下所示:
http://example.com/results.php?item=shoes&type=women
相反,我们希望访问者能够使用以下更简洁的 URL:
http://example.com/shoes/women
我们可以通过简单的替换或匹配选项之一来实现这些结果。
示例 1A:简单替换
我们将创建一个重写规则,执行简单的替换,简化长查询 URL:
RewriteRule ^shoes/women$ results.php?item=shoes&type=women
该规则将 shoes/women
映射到 results.php?item=shoes&type=women
。
示例 1B:匹配选项
在某些情况下,我们可能希望将查询字符串泛化以包括不同类型的鞋子。我们可以通过执行以下操作来实现:
- 使用竖线
|
,布尔“或”运算符,指定一系列选项 - 使用
()
分组匹配,然后使用$1
变量引用该组,1
代表第一个匹配的组
重写规则现在变为:
RewriteRule ^shoes/(men|women|youth) results.php?item=shoes&type=$1
上述规则匹配了以 shoes/
开头的 URL,后跟指定类型。这将修改原始 URL,以便:
http://example.com/shoes/men
变为:
http://example.com/results.php?item=shoes&type=men
这种匹配选项允许 Apache 在无需为每个选项创建单独的重写规则的情况下评估多个模式。
示例 1C:匹配字符集
然而,我们还希望指定任何项目,而不仅限于 /shoes
。因此,我们将执行以下操作:
- 编写一个匹配所有字母数字字符的 正则表达式。方括号表达式
[ ]
匹配其中的任何字符,+
匹配方括号中指定的任意数量的字符 - 分组匹配,并使用文件中的第二个变量
$2
引用它
RewriteRule ^([A-Za-z0-9]+)/(men|women|youth) results.php?item=$1&type=$2
上述示例将把:
http://example.com/pants/men
转换为:
http://example.com/results.php?item=pants&type=men
我们成功地扩展了匹配能力,以包括 URL 的多个方面。
示例 1D:传递查询字符串
本节不介绍任何新概念,而是解决可能出现的问题。使用上述示例,假设我们希望重定向 http://example.com/pants/men
,但会传递额外的查询字符串 ?page=2
。我们希望将以下 URL 映射为:
http://example.com/pants/men?page=2
到:
http://example.com/results.php?item=pants&type=men&page=2
如果您尝试使用当前设置访问上述 URL,您会发现查询字符串 page=2
丢失了。这很容易通过使用额外的 QSA
标志来解决,该标志会导致查询字符串被合并。修改重写规则以匹配以下内容将实现所需的行为。
RewriteRule ^([A-Za-z0-9]+)/(men|women|youth) results.php?item=$1&type=$2 [QSA]
示例 2: 使用逻辑添加条件
现在我们来看一下 RewriteCond
指令的使用。如果重写条件评估为真,那么 Apache 将考虑其后的 RewriteRule
。
示例 2A: 默认页面
之前,我们看到 Apache 处理对无效 URL 的请求时会提供一个 404 未找到 页面。然而,我们希望所有格式错误的 URL 被重定向回首页,而不是显示错误页面。通过使用条件,我们可以检查请求的文件是否存在。
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^admin/(.*)$ /admin/home
这将把类似 /admin/random_text
的请求重定向到 /admin/home
。
让我们解析上述规则:
%{REQUEST_FILENAME}
检查请求的字符串!-f
!
或 not 运算符表示如果请求的文件名不存在,则执行以下重写规则。RewriteRule
将请求重定向回/admin/home
遵循最佳实践,定义 404 ErrorDocument
。为此,我们将创建一个 ErrorDocument
规则,将 404 错误指向一个 error.html
页面:
ErrorDocument 404 /error.html
这将把任何导致 HTTP 404 响应的请求重定向到 error.html
页面。
示例 2B: IP 地址限制
RewriteCond
可以用于允许特定 IP 地址访问站点。
此示例阻止除 198.51.100.24 之外的所有地方的流量。
RewriteCond %{REMOTE_ADDR} !^(198\.51\.100\.24)$
RewriteRule (.*) - [F,L]
整个规则表示,如果请求资源的 IP 地址不是 198.51.100.24,则不允许访问。
简而言之:
%{REMOTE_ADDR}
是地址字符串!^(198\.51\.100\.24)$
否定 IP 地址。\
反斜杠用于转义.
点,否则它们将作为元字符用于匹配任何字符。F
标志禁止访问,L
标志表示这是最后一个要运行的规则,如果执行。
如果您更愿意阻止来自特定地址的访问,请改用以下内容:
RewriteCond %{REMOTE_ADDR} ^(198\.51\.100\.24)$
RewriteRule (.*) - [F,L]
尽管您可以使用其他方法来阻止或允许流量访问您的站点,但在 .htaccess
文件中设置限制是实现这些结果的最简单方法。
结论
在本教程中,我们使用了 .htaccess
文件来处理 RewriteRule
和 RewriteCond
指令。有许多理由使用重写规则,以下资源详细介绍了 mod_rewrite
模块的功能:
- Apache mod_rewrite 介绍
- mod_rewrite 文档
- mod_rewrite 速查表
mod_rewrite
模块是 Apache web 服务器的关键组件,您可以用它做很多事情。然而,事情并不总是按计划进行,当发生这种情况时,您可能会发现自己陷入重定向循环或出现模糊的 500 forbidden
错误。有关调试这些情况的提示,请参阅这篇 StackOverflow 帖子。