如何在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 的文档。

RewriteRulemod_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 文件来处理 RewriteRuleRewriteCond 指令。 使用重写规则的原因有很多,以下资源详细介绍了 mod_rewrite 模块的功能:

mod_rewrite 模块是 Apache Web 服务器的重要组成部分,你可以用它做很多事情。 但是,事情并不总是按计划进行,当发生这种情况时,您可能会发现自己遇到重定向循环或模棱两可的 500 forbidden 错误。 有关调试此类情况的提示,请查看 这个 StackOverflow 帖子