如何在CentOS7上为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
Output. . . 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
Output . . . 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
进入插入模式,然后添加或取消注释下面突出显示的行:
/etc/httpd/conf.modules.d/00-base.conf
# # 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
:
/etc/httpd/conf/httpd.conf
. . . <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
接下来,在默认文档根目录 /var/www/html
中为 Apache 创建一个 .htaccess
文件。
sudo vi /var/www/html/.htaccess
将以下行添加到文件顶部以激活 RewriteEngine
,它指示 Apache 处理以下任何规则:
/var/www/html/.htaccess
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 步 - 设置文件
我们将设置一个基本的重写规则,允许用户访问 about.html
页面,而无需在 Web 浏览器的地址栏中输入文件扩展名 (.html
)。 首先在文档根目录中创建一个 about.html
文件:
sudo vi /var/www/html/about.html
将以下 HTML 代码复制到文件中:
/var/www/html/about.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
我们希望 关于我们 页面的访问者无需键入 .html
即可访问它。 为此,我们将创建一个规则。
打开.htaccess
文件:
sudo vi /var/www/html/.htaccess
在 RewriteEngine On
行之后,添加以下内容:
/var/www/html/.htaccess
RewriteRule ^about$ about.html [NC]
保存并退出文件。
访问者现在可以使用 http://server_domain_or_IP/about
URL 访问 关于我们 页面。
让我们检查一下重写规则:
^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/关于
- server_domain_or_IP/关于
通过一个简单的重写规则,我们为用户如何访问 关于我们 页面添加了一个动态方面。
常见模式
现在我们对重写规则有了基本的了解,我们将在本节中探讨另外两个示例。
可以设置示例文件,但本教程不包括创建它们; 只是重写规则本身。
示例 1:使用 RewriteRule 简化查询字符串
Web 应用程序经常使用查询字符串,这些字符串使用问号字符 (?
) 附加到 URL 并由 & 字符 (&
) 分隔。 Apache 在匹配重写规则时会忽略这两个字符。 但是,有时可能需要查询字符串在页面之间传递数据。 例如,用 PHP 编写的搜索结果页面的 URL 可能如下所示:
http://example.com/results.php?item=shoes&type=women
相反,我们希望我们的访问者能够使用以下更简洁的 URL:
http://example.com/shoes/women
我们可以通过以下两种方式之一实现这些结果——通过简单的替换或匹配选项。
示例 1A:简单替换
我们将创建一个执行简单替换的重写规则,简化长查询 URL:
/var/www/html/.htaccess
RewriteRule ^shoes/women$ results.php?item=shoes&type=women
该规则将 shoes/women
映射到 results.php?item=shoes&type=women
。
示例 1B:匹配选项
在某些情况下,我们可能希望将查询字符串概括为包括不同类型的鞋子。 我们可以通过执行以下操作来完成此操作:
- 使用垂直管道
|
,布尔“OR”运算符指定一系列选项 - 使用
()
对匹配进行分组,然后使用$1
变量引用该组,第一个匹配组使用1
重写规则现在变为:
/var/www/html/.htaccess
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
作为文件中的第二个变量对其进行引用
/var/www/html/.htaccess
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
标志很容易解决这个问题,这会导致查询字符串被组合。 修改重写规则以匹配以下将实现所需的行为。
/var/www/html.html
RewriteRule ^([A-Za-z0-9]+)/(men|women|youth) results.php?item=$1&type=$2 [QSA]
示例 2:使用逻辑添加条件
现在我们来看看 RewriteCond
指令的使用。 如果重写条件的计算结果为真,则 Apache 会考虑其后面的 RewriteRule
。
示例 2A:默认页面
以前,我们看到 Apache 通过提供 404 Not Found 页面来处理对无效 URL 的请求。 但是,我们希望将所有格式错误的 URL 重定向回主页,而不是错误页面。 使用条件,我们可以检查请求的文件是否存在。
/var/www/html/.htacces
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
页面:
/var/www/html/.htaccess
ErrorDocument 404 /error.html
这会将导致 HTTP 404 响应的任何请求重定向到 error.html
页面。
示例 2B:IP 地址限制
RewriteCond
可用于允许通过特定 IP 地址访问站点。
此示例阻止来自任何地方的流量 除了 198.51.100.24。
/var/www/html/.htaccess
RewriteCond %{REMOTE_ADDR} !^(198\.51\.100\.24)$ RewriteRule (.*) - [F,L]
整个规则规定,如果请求资源的 IP 地址不是 198.51.100.24,则不允许访问。
简而言之:
%{REMOTE_ADDR}
是地址字符串!^(198\.51\.100\.24)$
否定 IP 地址。\
反斜杠转义了.
点,否则,它们充当用于匹配任何字符的元字符。F
标志禁止访问,L
标志表明这是最后运行的规则(如果执行)。
如果您希望 block 从特定地址访问,请改用以下命令:
/var/www/html/.htaccess
RewriteCond %{REMOTE_ADDR} ^(198\.51\.100\.24)$ RewriteRule (.*) - [F,L]
尽管您可以使用其他方法来阻止或允许访问您的站点,但在 .htaccess
文件中设置限制是实现这些结果的最简单方法。
结论
在本教程中,我们使用 .htaccess
文件来处理 RewriteRule
和 RewriteCond
指令。 使用重写规则的原因有很多,以下资源详细介绍了 mod_rewrite
模块的功能:
mod_rewrite
模块是 Apache Web 服务器的重要组成部分,你可以用它做很多事情。 但是,事情并不总是按计划进行,当发生这种情况时,您可能会发现自己遇到重定向循环或模棱两可的 500 forbidden
错误。 有关调试此类情况的提示,请查看 这个 StackOverflow 帖子 。