如何在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.html
或 example.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 1 和 part 2 中找到更多的重写规则,以及如何防止热链接。
结论
mod_rewrite
可以有效地用于确保人类可读的 URL。 然而,.htaccess
文件本身的用途远不止这个模块,而且应该注意,可以安装许多其他 Apache 模块来扩展其功能。
还有其他资源详细介绍了 mod_rewrite
的功能:
mod_rewrite
是 Web 应用程序安全性的关键模块,但有时会导致重定向循环或无处不在、模棱两可的 500 forbidden
错误。 有关调试 .htaccess
的提示,请参阅 this StackOverflow post。
重写规则是用正则表达式编写的。 要成为专家,请参考这个 教程所有关于正则表达式 。
为了快速分析您的正则表达式模式,这里有一个 在线调试器 ,它可以提供对正则表达式模式的即时反馈和实时解释。