如何在Ubuntu14.04上为Apache设置mod rewrite

来自菜鸟教程
跳转至:导航、​搜索

介绍

在本教程中,我们将激活并学习如何使用 Apache2 的 mod_rewrite 模块来管理 URL 重写。 该工具允许我们以更简洁的方式重写 URL,将人类可读的路径转换为代码友好的查询字符串。

本指南分为两部分:第一部分设置示例 Web 应用程序,第二部分解释常用的重写规则。

先决条件

要遵循本教程,您将需要:

  • 一个新鲜的 Ubuntu 14.04 Droplet
  • 一个sudo非root用户,可以按照本教程的步骤2和3进行设置

第 1 步 — 安装 Apache

在这一步中,我们将使用一个名为 apt-get 的内置 软件包安装程序。 它极大地简化了管理并促进了干净的安装。

首先,更新系统的包索引。 这将确保旧的或过时的软件包不会干扰安装。

sudo apt-get update

Apache2 就是前面提到的 HTTP 服务器,也是世界上最常用的。 要安装它,请运行以下命令:

sudo apt-get install apache2

有关 Nginx 和 Apache2 这两种最流行的开源 Web 服务器之间的差异的信息,请参阅 这篇文章

第 2 步 — 启用 mod_rewrite

现在,我们需要激活 mod_rewrite

sudo a2enmod rewrite

这将激活模块或提醒您该模块已经生效。 要使这些更改生效,请重新启动 Apache。

sudo service apache2 restart

第 3 步 — 设置 .htaccess

在本节中,我们将设置一个 .htaccess 文件以简化重写规则管理。

.htaccess 文件允许我们在不访问服务器配置文件的情况下修改我们的重写规则。 因此,.htaccess 对您的 Web 应用程序的安全性至关重要。 文件名前面的句点确保文件被隐藏。

在开始之前,我们需要设置并保护更多设置。

首先,允许更改 .htaccess 文件。 使用 nano 或您喜欢的文本编辑器打开默认的 Apache 配置文件。

sudo nano /etc/apache2/sites-enabled/000-default.conf

在该文件中,您会在第 1 行找到 <VirtualHost *:80> 块。 在该块内,添加以下块:

/etc/apache2/sites-available/default<Directory /var/www/html>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
</Directory>

您的文件现在应该与以下内容匹配。 确保所有块都正确缩进。

/etc/apache2/sites-available/default<VirtualHost *:80>
    <Directory /var/www/html>
    
        . . .
        
    </Directory>
    
    . . .
</VirtualHost>

要使这些更改生效,请重新启动 Apache。

sudo service apache2 restart

现在,创建 .htaccess 文件。

sudo nano /var/www/html/.htaccess

在新文件的顶部添加第一行以激活 RewriteEngine

/var/www/html/.htaccessRewriteEngine on

保存并退出文件。

为确保其他用户只能读取您的.htaccess,请运行以下命令更新权限。

sudo chmod 644 /var/www/html/.htaccess

您现在有一个可操作的 .htaccess 文件,用于管理您的 Web 应用程序的路由规则。

第 4 步 — 设置文件

在本节中,我们将设置一个基本的 URL 重写,它将漂亮的 URL 转换为代码的实际路径。 具体来说,我们将允许用户访问example.com/about

我们将首先创建一个名为 about.html 的文件。

sudo nano /var/www/html/about.html

将以下代码复制到 HTML 页面中。

/var/www/html/about.html<html>
    <head>
        <title>About Us</title>
    </head>
    <body>
        <h1>About Us</h1>
    </body>
</html>

您可以通过 your_server_ip/about.htmlexample.com/about.html 访问您的 Web 应用程序。 现在注意到只有 about.html 是可访问的; 如果您尝试访问 your_server_ip/about,您将收到 Not Found 错误。 我们希望用户改为访问 about。 我们的重写规则将允许这个功能。

打开 .htaccess 文件。

sudo nano /var/www/html/.htaccess

在第一行之后,添加以下内容。

/var/www/html/.htaccessRewriteRule ^about$ about.html [NC]

您的文件现在应该与以下内容相同。

/var/www/html/.htaccessRewriteEngine on
RewriteRule ^about$ about.html [NC]

恭喜。 您现在可以在浏览器中访问example.com/about

这是一个很好的简单示例,显示了所有重写规则遵循的一般语法。

^about$ 是从 URL 中匹配的字符串。 也就是说,这是查看者在浏览器中键入的内容。 我们的示例使用了一些 元字符

  • ^ 表示 URL 的开始,在 example.com/ 被剥离之后。
  • $表示URL结束
  • about 匹配字符串“about”

about.html是用户访问的实际路径; 也就是说,Apache 仍将提供 about.html 文件。

[NC] 是一个 标志 ,它忽略 URL 中的大小写。

使用上面显示的规则,以下 URL 将指向 about.html

  • example.com/about
  • example.com/About
  • example.com/about.html

以下不会:

  • example.com/about/
  • example.com/contact

常见模式

在本节中,我们将展示一些常用的指令。

您的 Web 应用程序现在正在运行,并由受保护的 .htaccess 文件管理。 上面包含了最简单的示例。 我们将在本节中探讨另外两个示例。

如果您愿意,可以在结果路径中设置示例文件,但本教程不包括创建 HTML 和 PHP 文件; 只是重写的规则。

示例 1:使用 RewriteRule 简化查询字符串

所有 RewriteRule 都遵循以下格式:

RewriteRule pattern substitution [flags]
  • RewriteRule:指定指令RewriteRule
  • pattern:匹配所需字符串的正则表达式
  • substitution:实际 URL 的路径
  • flags:可以修改规则的可选参数

Web 应用程序经常使用 查询字符串 ,这些字符串使用 ? 问号附加到 URL,并使用 & 和号分隔。 这些在匹配重写规则时被忽略。 但是,有时可能需要查询字符串在页面之间传递数据。 例如,用 PHP 编写的搜索结果页面可能会使用类似于以下内容的内容:

http://example.com/results.php?item=shirt&season=summer

在此示例中,我们希望将其简化为:

http://example.com/shirt/summer

示例 1A:简单替换

使用重写规则,我们可以使用以下内容:

/var/www/html/.htaccessRewriteRule ^shirt/summer$ results.php?item=shirt&season=summer

以上是不言自明的,因为它实际上将 shirt/summer 映射到 results.php?item=shirt&season=summer。 这样就达到了我们想要的效果。

示例 1B:匹配选项

但是,我们想将其概括为包括所有季节。 因此,我们将执行以下操作:

  • 使用 | 布尔值指定一系列选项,意思是“或”
  • 使用 () 对匹配进行分组,然后使用 $1 引用该组,第一个匹配组使用 1

重写规则现在变为:

/var/www/html/.htaccessRewriteRule ^shirt/(summer|winter|fall|spring) results.php?item=shirt&season=$1

上面显示的规则匹配 shirt/ 的 URL,后跟指定的季节。 该季节使用 () 进行分组,然后在后续路径中使用 $1 进行引用。 例如,这意味着:

http://example.com/shirt/winter

变成:

http://example.com/results.php?item=shirt&season=winter

这也达到了预期的效果。

示例 1C:匹配字符集

但是,我们还想指定任何类型的项目,而不仅仅是 /shirt 处的 URL。 因此,我们将执行以下操作:

  • 编写一个匹配所有字母数字字符的 正则表达式 。 括号表达式 [] 匹配其中的任何字符,而 + 匹配括号中指定的任意数量的字符
  • 对匹配进行分组,并使用 $2 作为文件中的第二个变量对其进行引用
/var/www/html/.htaccessRewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2

以上将转换,例如:

http://example.com/pants/summer

到:

http://example.com/results.php?item=pants&season=summer

示例 1D:传递查询字符串

本节不介绍任何新概念,而是解决可能出现的问题。 使用上面的例子,假设我们想要重定向 http://example.com/pants/summer 但会传递一个额外的查询字符串 ?page=2。 我们想要以下内容:

http://example.com/pants/summer?page=2

映射到:

http://example.com/results.php?item=pants&season=summer&page=2

如果您尝试使用我们当前的设置访问上述 URL,您会发现查询字符串 page=2 丢失了。 使用附加的 QSA 标志可以轻松解决此问题。 修改重写规则以匹配以下内容,将实现所需的行为。

/var/www/html/.htaccessRewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2 [QSA]

示例 2:使用逻辑添加条件

RewriteCond 让我们在重写规则中添加条件。 所有 RewriteCond 都遵循以下格式:

RewriteCond TestString Condition [Flags]
  • RewriteCond:指定RewriteCond指令
  • TestString:要测试的字符串
  • Condition:要匹配的模式
  • Flags:可能修改条件的可选参数

如果 RewriteCond 计算结果为真,则将考虑紧随其后的 RewriteRule

示例 2A:默认页面

在一个虚构的管理面板中,我们可能希望将所有格式错误的 URL 引导回主页,而不是用 404 问候用户。 使用条件,我们可以检查请求的文件是否存在。

/var/www/html/.htaccessRewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^admin/(.*)$ /admin/home

这会将 /admin/blargh 之类的内容重定向到 /admin/home

有了以上内容:

  • %{REQUEST_FILENAME} 是要检查的字符串
  • !-f 对文件名使用 ! 非运算符
  • RewriteRule 将所有请求重定向回 /admin/home

请注意,在语法和技术上更正确的方法是定义 404 ErrorDocument

/var/www/html/.htaccessErrorDocument 404 /error.html

示例 2B:IP 访问限制

尽管这也可以使用其他方法实现,但 RewriteCond 可用于限制对一个 IP 或一组 IP 地址的访问。

此示例阻止来自任何地方的流量 除了 12.34.56.789。

/var/www/html/.htaccessRewriteCond %{REMOTE_ADDR} !^(12\.34\.56\.789)$
RewriteRule (.*) - [F,L]

这个例子只是对旧 mod_rewrite 文章 中的 例子 3 的否定。 整条语句为“如果地址是 not 12.34.56.789,则不允许访问。”

简而言之:

  • %{REMOTE_ADDR} 是地址字符串
  • !^(12\.34\.56\.789)$ 使用 \ 反斜杠转义所有 . 句点,并使用 ! 否定 IP 地址
  • F 标志禁止访问,L 标志表明这是最后运行的规则,如果执行

如果您更愿意 block 12.34.56.789,请改用:

/var/www/html/.htaccessRewriteCond %{REMOTE_ADDR} ^(12\.34\.56\.789)$
RewriteRule (.*) - [F,L]

您可以在原文章的 part 1part 2 中找到更多的重写规则,以及如何防止热链接。

结论

mod_rewrite 可以有效地用于确保人类可读的 URL。 然而,.htaccess 文件本身的用途远不止这个模块,而且应该注意,可以安装许多其他 Apache 模块来扩展其功能。

还有其他资源详细介绍了 mod_rewrite 的功能:

mod_rewrite 是 Web 应用程序安全性的关键模块,但有时会导致重定向循环或无处不在、模棱两可的 500 forbidden 错误。 有关调试 .htaccess 的提示,请参阅 this StackOverflow post

重写规则是用正则表达式编写的。 要成为专家,请参考这个 教程所有关于正则表达式

为了快速分析您的正则表达式模式,这里有一个 在线调试器 ,它可以提供对正则表达式模式的即时反馈和实时解释。