简介
在这篇教程中,我们会激活并且学习如何管理 Apache2 的 mod_rewrite 模块。这个工具允许我们使用简洁的方式去重写 URL,将对人类可读的路径转换成代码友好的查询字符串。
本教程分为两部分:第一部分会设置一个简单的 WEB 应用程序,第二部分会阐述一些常用的重写规则。
先决条件
为了能顺利完成本教程,您需要:
- 一个新的 Ubuntu 14.04 系统
- 一个具有 sudo 权限的非 root 用户帐号,这样您才能够完成本教程以下的第 2 和 第 3 步
步骤一、安装 Apache
在此步骤中,我们会使用一个内置的包安装器——apt-get。它大大简化了管理和促进一个干净的安装。
首先,更新系统的包索引。这样可以确保那些旧的或已经过期的包不会干扰到安装。
$ sudo apt-get update
Apache2 是世界上最常用的 HTTP 服务器,要安装它,只需要运行以下命令:
$ sudo apt-get install apache2
更多关于 Nginx 和 Apache2 (这两个最流行的开源 WEB 服务器)的区别的信息,请看这篇文章。
步骤二、开启 mod_rewrite 模块
现在我们需要激活 mod_write 模块。
$ sudo a2enmod rewrite
这个命令会激活模块或者提示说模块已经启用了。要使这些改变生效,需要重启 Apache 。
$ sudo service apache2 restart
步骤三、设置 .htaccess
在这一步中,我们会设置一个具有简单重写规则的 .htaccess 的文件。
一个 .htaccess 文件允许我们在不访问服务器配置文件的情况下去修改我们的重写规则。正是因为这个原因,.htaccess 文件对于 WEB 应用的安全性非常重要。文件名前面的点号就是确保该文件是隐藏的。
在开始之前,我们需要做多一些安全方面的设置。
首先,允许在 .htaccess 文件中做出更改。使用 nano 或者你最喜欢的文本编辑器打开默认的 Apache 配置文件。
$ sudo nano /etc/apache2/sites-enabled/000-default.conf
在文件中的第一行你会看到 <Directory /var/www/html>
块 。在该块内容里面,添加如下内容块:
/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
在新文件的顶部添加一行来激活重写引擎。
/var/www/html/.htaccess
RewriteEngine on
保存并退出文件。
为了确保其它用户只能读取 .htaccess 文件,运行以下命令来更新权限。
$ sudo chmod 644 /var/www/html/.htaccess
现在您已经有一个给你的 WEB 应用设置路由规则的可用的 .htaccess 文件了。
步骤四、设置文件
在这一步中,我们会设置一个基本的 URL 重写规则,它会将 URL 转换成实际的代码路径。
很确定的,我们可以使用 example.com/about 来访问。
$ sudo nano /var/www/html/about.html
将下面的代码复制到 HTML 页面。
/var/www/html/about.html
<html>
<head>
<title>About Us</title>
</head>
<body>
<h1>About Us</title>
</body>
</html>
你可以使用 server_ip/about.html 或者 example.com/about.html 来访问你的 WEB 应用。现在请注意,只有 about.html 可以访问;如果你访问 server_ip/about ,你会得到一个 404 错误的。我们想要使用 server_ip/about 来访问,我们的重写规则就会非常有用了。
打开 .htaccess 文件:
$ sudo nano /var/www/html/.htaccess
在第一行之后,添加下面的内容:
/var/www/html/.htaccess RewriteRule ^about$ about.html [NC]
你的文件应该与下面的相同:
/var/www/html/.htaccess RewriteEngine 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 pattern substitution [flags]
- 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/.htaccess RewriteRule ^shirt/summer$ results.php?item=shirt&season=summer
以上的例子是很明显地,它实际上是将 shirt/summer
映射到 esults.php?item=shirt&season=summer
。 这满足我们的期望效果了。
例 1B、匹配选项
然后,我们需要推广到所有的季节。因此,我们可以如下做:
- 使用 | (意为“或”)来指定一系列选项
- 使用 () 将该匹配组织起来,然后使用
$1
来引用,1 代表第一个匹配项
这重写规则现在变成:
/var/www/html/.htaccess RewriteRule ^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
。因此我们需要做以下的事情:
- 写一个匹配所有字符数字的正则表达式。这方括号 [] 表达式匹配它里面的所有的字符,+ 匹配方括号里面指定的字符任意多次。
- 组织匹配项,然后使用
$2
来引用文件中的第二个变量
/var/www/html/.htaccess RewriteRule ^([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/.htaccess RewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2 [QSA]
例 2、添加逻辑条件
RewritedCond
允许我们添加条件到重写规则。所有的
RewriteCond TestString Condition [Flags]
- RewriteCond : 指定是
RewriteCond
指令 - TestString : 需要检测的字符串
- Condition : 需要匹配的模式
- Flags : 可以修改条件的可选参数
例 2A、默认页面
在一个虚构的管理员面板中,我们可能想要将所有非法的 URL 定向到首页,而不是使用 4040 来问候用户。使用一个条件,我们可以检测到一个文件是否存在。
/var/www/html/.htaccess RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^admin/(.*)$ /admin/home
这样子会将类似于 /admin/blargh
的 URL 重定向到 /admin/home
。
关于上面的规则:
- %{REQUEST_FILENAME} 是需要检测的字符串
- !-f 在文件名前面使用 ! 非运算符
- RewriteRule 重定向所有的查询到
/admin/home
注意,一个正确的语法技术来定义 404 ErrorDocument。
/var/www/html/.htaccess ErrorDocument 404 /error.html
例 2B、IP 访问限制
RewreteCond 可以用来限制只能通过一个 IP 或 IP 集合来访问,虽然这个同样可以使用其它方法达到。
这个例子的效果是除了 12.34.56.789 之外,其它的 IP 都将被拒绝访问。
/var/www/html/.htaccess RewriteCond %{REMOTE_ADDR} !^(12\.34\.56\.789)$ RewriteRule (.*) - [F,L]
这整个语句的意思是“如果 IP 地址不是 12.34.56.789,则不允许访问”。
说明:
- %{REMOTE_ADDR} 是 IP 地址字符串
- !^(12\.34\.56\.789)$ 使用 \ 对所有的 . 进行转义,使用 ! 对 IP 地址进行非运算
- F 标志是禁止访问,L 标志说明这是最后一条规则(如果执行的话)
如果您想要禁止 12.34.56.789 ,使用这个来代替:
/var/www/html/.htaccess RewriteCond %{REMOTE_ADDR} ^(12\.34\.56\.789)$ RewriteRule (.*) - [F,L]
如果您想了解更多重写规则,如何防止热链接,在 part1 和 part2 。
总结
mod_rewrite
可以很容易地确保人类可读的 URL。.htaccess 文件不仅仅用于这个模块,需要注意的是,许多其它的 Apache 模块也会被安装来扩展它的功能。
这里有些资源来阐述 mod_rewrite 的功能:
mod_rewrite 是 WEB 应用安全中重要的模块,但是有时它可能会导致重定向循环、模棱两可的500禁止错误。关于调式 .htaccess 的相关技巧,请查看 StackOverflow 的帖子。
重写规则是用正则表达式来写的。想了解更多关于正则表达式的知识,情查看正则表达式全解。
要快速分析您的正则表达式模式,这里有一个在线调试器,它可以为您的正则表达式提供即时的反馈和实时的解释。
END
本文作者: chenishr
本文标题:《在 Ubuntu 14.04 上设置 Apache 的重写模块》
本文地址: http://blog.chenishr.com/?p=578
©版权所有,除非注明, 永在路上文章均为原创,转载请以链接形式注明出处和作者细信息。