提供:ZStack云计算
关于Mod_Rewrite
大家可以回忆自己上一次访问购物网站的经历。在打开对应页面时,URL通常会显示为以下形式:
gizmo.com/latest_and_greatest/specific_gadgets/exactly_what_youre_looking_for
这并不是说网站会花时间为大家的购买流程设置独立的目录,而是因为MOd_Rewrite模块发挥了作用。Mod_Rewrite允许大家根据需要生成定制化的简化URL。事实上,实际URL可能如下所示:
http://www.gizmo.com/gp/itemB004RYVI0Q/ref=as_li_ss_tl?
在本教程中,我们将探讨如何激活Mod_Rewrite、如何创建并使用需要的.htaccess页面以及如何设置URL rewrite。
目录
- [如何激活Mod_Rewrite](https://www.digitalocean.com/community/tutorials/how-to-set-up-mod_rewrite#Section 1)
- [如何创建并使用htaccess文件](https://www.digitalocean.com/community/tutorials/how-to-set-up-mod_rewrite#Section 2)
- [如何使用Rewrite规则](https://www.digitalocean.com/community/tutorials/how-to-set-up-mod_rewrite#Section 3)
- [如何使用Rewrite Cond指令](https://www.digitalocean.com/community/articles/how-to-set-up-mod_rewrite-page-2#Section 4)
- [信息来源](https://www.digitalocean.com/community/articles/how-to-set-up-mod_rewrite-page-2#Section 5)
设置
本教程中的各个步骤要求大家首先拥有具备root权限的用户。大家可以参阅此文的第三与第四步了解如何在Ubuntu 上设置这样的用户。
另外,大家还需要在服务器上安装apache。如果还没有安装,各位可以使用以下命令进行下载:
sudo apt-get install apache2
第一章——如何激活Mod_Rewrite
在开始之前,我们首先需要激活apache mod_rewrite模块:
sudo a2enmod rewrite
此命令会激活该模块——如果其已经被激活,则会显示“Module rewrite already enabled”。
第二章——关于.htaccess文件:
模块激活后,我们可以在网站目录中创建一个.htaccess文件设置URL rewrite。
.htaccess文件用于配置网站细节,且无需涉及服务器的自身配置文件。由于文件名本身以.为开头,因此会在文件夹中自动隐藏。
另外,.htaccess文件的放置位置也非常重要。该文件中的配置会影响到目录中的一切,包括各次级目录。
大家可以在文本编辑器中创建此文件,以确保其名称不包含任何其它扩展,而后通过ftp客户端将其上传至站点。
另外,大家可以使用以下命令在终端处创建该文件(注意替换实际域名):
sudo nano /var/www/example.com/.htaccess
如何在.htaccess文件内实现变更
为了允许.htaccess文件覆盖标准网站配置,大家首先打开该文件:
sudo nano /etc/apache2/sites-available/default
在文件中找到以下部分,将该行中的None变更为All:
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
完成后保存并退出,重启apache。
sudo service apache2 restart
现在已经可以对站点URL进行重写了。
第三章——如何重写URL
完整的URL重写操作存在于.htaccess文件内。
总体来讲,全部URL rewrite命令都遵循以下格式:
RewriteRule Pattern Substitution [OptionalFlags]
下面来看其中各部分的含义:
- RewriteRule: 大家可在此部分中写入需要使用的mod_rewrite指令名称。
- Pattern: 用于通过正规表达式解释被请求的URL。本教程中不涉及该表达式,大家可参阅此文。
- Substitution: 即希望显示信息的实际页面URL,由于存在大量php参数或者大段数字而难于记忆,例如www.cityzoo.com/animals.php?mammals=seals。
- Optional Flags: Rewrite Rule指令末尾处的标签,可变更该表达式的具体行为。部分常用标记包括[F],禁用该URL;[NC],无视能力强制执行规则;[R=301]或者[R=302],控制希望使用的重新定向代码;[L],指定此为系列中的最后一条规则。
三项URL Rewrite示例:
示例1:前往A页面,找到B页面:
这是最为基本的URL rewrite示例,访问者输入某条URL以访问目标站点,但会被重新定向至其它位置。
下面我们假设站点分为两个独立页面,其一为Apples(apples.html),另一为Oranges(organes.html):
将以下代码复制至Apples页面:
<html>
<head>
<title>Apples</title>
</head>
<body>
<h1>This page is about Apples</h1>
</body>
</html>
完成后,再设定oragnes页面。
现在打开.htaccess文件。
sudo nano /var/www/example.com/.htaccess
向文件中添加以下命令:
RewriteEngine on
RewriteRule ^oranges.html$ apples.html
保存并退出。
一切就绪后,以“/oranges.html”为结尾访问该站点,则全部显示信息将来自“/apples.html”站点。
下面进行具体解释:
- ^oranges.html: 指定页面的启动方式。其中^符号表示字符串开头。换言之,如果该页面的URL并非以oranges开头(例如navel_oranges.html),则不符合重写规则,即不会被定向至apples.html。
-
:此符号代表URL的结尾。如果字符串内在 后仍有内容,则该网页不符合重写规则。 - apples.html: 浏览器的实际流量定向目标。
示例2:URL中包含参数的网站。如何将其转换为子目录形式。
在上一个示例中,我们只需要在不同站点间往来切换。但在以下实例内,我们需要解决另一种常见问题——URL内包含参数:
例如以下URL:
http://example.com/results.php?products=apple
其更简明的显示方式应为:
http://example.com/products/apple
在.htaccess文件内的各行应为:
RewriteEngine on
RewriteRule ^products/([A-Za-z0-9-]+)/?$ results.php?products=$1 [NC]
现在具体解释:
- ^products: 为了完成捕捉与重新路由,该URL必须以products开头(注意,其只代表域名后的文本内容而非单词含义)。如果以其它内容开头,则不符合本规则。
- ([A-Za-z0-9-]+): 括号中的内容指可被输入至URL的信息。换言之,此URL将在/products/之后被重写为可反映访问者输入内容的形式。
- +: 加号代表括号中的部分可为一个或者多个字符。
- /?
: 用于指明字符串结尾。而?则允许字符串的最末字符为斜杠(即/,但并非必需)。 - results.php?products=
1:其中 1指定模式中的字符串该放置在哪里。具体来讲,其会对”([A-Za-z0-9-]+):”部分中的任意访问者写入内容进行捕捉,并在处理完成后由浏览器显示来自第二条URL的信息。 - [NC]: 语句结束标记,代表该规则应忽略所有字符串中包含字符的情况。
示例3:站点URL太过冗长,需要清理
这类情况往往表现为URL太长且内容极为复杂。
以以下URL为例:
http://example.com/results.php?products=produce&type=fruit&species=apple
在清理之后,URL应该被简化为:
http://example.com/produce/fruit/apple
为了完成这一目标,我们需要在.htaccess文件中添加以下行:
RewriteEngine on
RewriteRule ^(meat|produce|dairy)/([^/.]+)/([^/.]+)$ results.php?products=$1&type=$2&species=$3
下面具体进行解释:
- 第一个^标记表达式开始。
- (meat|produce|dairy): 如果我们希望限制能够输入的选项,则可指定允许接受的值:在本示例中,即各种杂货。如果除这三个关键词以外的输入结果出现,则URL不进行重写。
- ([^/.]+)指定任何以正斜杠与插入符号间的字符,本示例中为正斜杠或者句号(/或.)。
- results.php?products=1&type=2&species=
3:取括号中的每一个值,而后应用到较长URL内表达具体部分。 1指定第一括号,2为第二个, 3则为第三个。
Rewrite条件
以上三个示例说明了如何将URL重写为更简单且容易记住的形式。
Rewrite Rules也可包含各类条件,从而确保rewrite只在特定情况下发生。
示例1:如何防止盗链
盗链是指在其它服务器上使用另一服务器图片或者对象的作法。这可能给我们的服务器带宽造成负担,并使得访问者不再前往资源所在站点。
大家可以将一直指向本站点对象的盗链定向至其它提示图片,或者直接禁用盗链。
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?example\.com/.*$ [NC]
RewriteRule .*\.(gif|jpeg|png)$ http://www.example.com/unpleasantness.jpg [R,NC,L]
下面进行解释:
- %{HTTP_REFERER}: 引用流量的来源。其中的百分号是一条apache变量。
- !: 感叹号会否定接下来的模式。实际上,其会指出后来的任何条件都不再受rewrite rule影响。
- ^$: 仍然作为字符串的开头与结尾。在本示例中,由于二者之间没有任何内容,所以不存在引用。换言之,此行指明该直接链接不受rewrite rule影响。
- 第二项条件再次进行引用。
- !^http://(www.)?example.com/.*$: 感叹号指明该引用并非来自我们自己的站点。
-
最后,我们将盗链指向某些令人不快的图片,作为对盗链者的警告。如果想直接禁止全部指向图片的盗链,则可重写最后一行规则,但将替代目标更换为禁止页面:
RewriteRule .*.(gif|jpeg|png)$ - [F]
示例2:如何向URL中添加www
另一项实用技巧在于,我们可以利用mod_rewrite向域名中添加www。尽管example.com与www.example.com明显属于同一站点,但搜索引擎有时候会将其作为重复项。
为了解决这个问题,我们可以选择始终删除或者添加www。在本示例中,我们将了解如何保证www始终存在。
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.com$
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301]
下面进行具体解释:
- %{HTTP_HOST}: 指向网站的请求URL
- ^example.com$: 解释所请求的页面应为example.com
- ^(.*)$ :Rewrite rule表明域名后可添加任意文本。
- [R=301]: 本标记表示该URL已经被重新定向,而301表示此为永久重新定向。如果属于临时定向,则为302。
这样一来,全部example.com都会显示为www.example.com。
示例3:屏蔽特定IP地址
我们可以借此避免来自特定IP地址的恶意人士访问自己的站点。
RewriteCond %{REMOTE_ADDR} ^(12\.34\.56\.789)$
RewriteRule (.*) - [F,L]
下面进行具体解释:
- %{REMOTE_ADDR}: 代表需要屏蔽的站点访问来源IP地址。
- ^(12.34.56.789)$:大家可以在这里输入恶意IP地址。请注意,其中的反斜杠非常重要,其将.指定为周期而非标准正则表达式中的通配符。
- (.*): 表明来自任意被屏蔽IP的文本都会触发rewrite rule。
- [F,L]: 标记规则结束。[F]禁止访问,[L]阻止其后的应用任何规则,即标注结尾。
信息来源
通过以上各章节,大家应该已经对Mod_Rewrite有了初步了解。
这个主题还有很大的讨论空间,我们也能够通过其它途径进一步扩展其实用性与灵活性。
推荐大家参阅以下链接:
本文来源自DigitalOcean Community。英文原文:How To Set Up Mod_Rewrite By Etel Sverdlov
翻译:diradw