URL重定向是.htaccess的重头戏,它可以将长地址转为短地址、将动态地址转为静态地址、重定向丢失的页面、防止盗链、实现自动语言转换等。笔者觉得难点是在正则表达式的运用和理解上。有关htaccess的正则表达式用法,请查阅本站《.htaccess正则表达式》一文。
实现所有这些神奇功能的模块叫做mod_rewrite,请确保你的服务器安装并启用了该模块:
sudo a2enmod rewrite我们一般会把所有涉及URL重写或者重定向的代码这样放置:
<IfModule mod_rewrite.c> # Turn on rewrite engine Options +FollowSymlinks RewriteEngine on # More rules below ... </IfModule>一些我们需要注意的地方:
FollowSymlinks必须启用,这是rewrite引擎的安全需求。 通常FollowSymlinks在Apache的主配置文件中就已经启用了,所以通常可以省略。 RewriteEngine命令用于启用rewrite引擎 IfModule命令用于判断Apache是否安装了mod_rewrite模块,之后笔者会省略该命令,但不代表这是个好习惯。 mod_rewrite会处理所有提交给Apache的URL请求,并与之后的规则进行匹配下面我们开始讲解一些例子。
注意事项:
该RewriteRule能够将.htm静态页面映射到.php动态页面 如果通过.htm进入,浏览器地址栏显示的是.htm扩展名,但服务器上实际执行的是.php 必须保证服务器上有对应的.php,否则会404 浏览器和搜索引擎可以同时通过.htm和.php访问网页 如果该目录上存在.htm,将被忽略 [NC]表示“不区分大小写”,更多类似定义请参考本站《.htaccess正则表达式》一文注意事项:
该RewriteRule能够将.htm静态页面重定向到.php动态页面 如果通过.htm进入,浏览器地址栏会自动转为.php,这也是重定向的本质 必须保证服务器上有对应的.php,否则会404 浏览器和搜索引擎可以同时通过.htm和.php访问网页 如果该目录上存在.htm,将被忽略 RewriteBase定义了重写基准目录。 例如,如果你将虚拟站点设置在/var/www目录下,删除这行将会导致重定向到http://yourdomain.com/var/www/1.php。显然这是找不到的,而且你也不会希望用户看见你的服务器的目录结构。 再举个例子,如果RewriteBase /base/,那么将会重定向到http://yourdomain.com/base/1.php。 对于重写基准目录,我们还可以通过将$1.php变成/$1.php实现直接变换,这时就可以将RewriteBase省略。 字母R表示临时重定向,相当于[R=302,NC]。关于重定向代码,请参考本站《HTTP协议重定向编码》 字母L表示如果能匹配本条规则,那么本条规则是最后一条(Last),忽略之后的规则。在讨论R=302临时重定向后,理解R=301永久重定向也就容易多了:
RewriteEngine on RewriteRule ^(.*)$ http://newdomain.com/$1 [R=301,NC,L] 这个规则告诉浏览器和搜索引擎,网站地址发生了永久性变更,用户的URL请求将会被发送给新的域名(主机)处理。 由于是重定向到新的主机地址,RewriteBase也就没有出现的必要了。利用URL重写,我们可以很方便地实现长短地址的转换,但是用重定向就不合适了。
RewriteEngine On RewriteRule ^grab /public/files/download/download.php若访问 http://mysite/grab?file=my.zip 则会执行该页面: http://mysite/public/files/download/download.php?file=my.zip
如果你不凑巧买到了不支持多域名的主机,那么.htaccess或许可以帮助你。现在假设你有域名domain-one.com和domain-two.com,并且在服务器根目录有对应文件夹one和two,那么通过下面的改写就能让Apache同时接受者两个域名的请求:
#two domains served from one root.. RewriteCond %{HTTP_HOST} domain-one.com RewriteCond %{REQUEST_URI} !^/one RewriteRule ^(.*)$ /one/$1 [L] RewriteCond %{HTTP_HOST} domain-two.com RewriteCond %{REQUEST_URI} !^/two RewriteRule ^(.*)$ /two/$1 [L]查询字符串是指URL请求中“问号”后面的部分。比如,http://mysite/grab?foo=bar中粗体部分就是查询字符串,其中变量名是foo,值是bar。
QSA标志( Query String Appending)用于在URI中截取查询字符串,这个截取操作是通过小括号正则表达式实现的:
RewriteEngine On RewriteRule /pages/(.+) /page.php?page=$1 [QSA] 将会把请求/pages/123?one=two 映射到 /page.php?page=123&one=two 注意粗体部分几乎是相同的,除了“问号”变成了“与”符号 如果没有QSA标志,那么会映射到/page.php?page=123。 如果没有用到小括号正则表达式,就不需要QSA,这在上节“长短地址转换”中已经例证过了。 小括号正则表达式可以截取查询字符串中的内容,但是如果没有开启QSA标志,那么在/page.php?page=$1中“问号”之后将会被剥离丢弃。这种特性可以用于实现“剥离查询字符串”通过QSA,我们可以将简单链接/simple/flat/link/ 映射成 server-side.php?first-var=flat&second-var=link
RewriteEngine On RewriteRule ^/([^/]+)/([^/]+)/? /index.php?first-var=$1&second-var=$2 [QSA]只需在要开始剥离的链接后面加个“问号”,并且不要启用QSA标志,就可剥离查询字符串
RewriteEngine On # Whatever QS is RewriteCond %{QUERY_STRING} . # I don't want it with Question mark RewriteRule foo.php(.*) /foo.php? [L]我们在第一篇.htaccess基础中提到了很多有用的访问控制方法,其实通过Rewrite也能实现类似的功能,而且可以更强大!
之前利用Order、Files及FilesMatch命令实现的访问控制可以满足大部分要求,但是当用户被拒绝时,他们看到的是硕大的“403 Forbidden”,如果你不想伤害用户的感情,就需要显示一些别的东西,通过Rewrite就可以实现这个特性:
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !^(.+)\.css$ RewriteCond %{REQUEST_FILENAME} !^(.+)\.js$ RewriteCond %{REQUEST_FILENAME} !special.zip$ RewriteRule ^(.+)$ /chat/ [NC] 该规则将仅允许用户请求.css, .js类型的文件,还有special.zip文件 RewriteRule 后面指定了限制规则:映射到/char/目录下处理 RewriteCond 后面的“感叹号”(!)起到了“否定”作用,它表明,对不满足后面正则表达式者应用RewriteRule规则,也就是对当前类型的文件将不应用规则 RewriteCond 之间是以逻辑“与”连接的,也就是只有当三个条件都不满足时才执行RewriteRule 该规则也会限制访问.htm, .jpg等格式 该规则不可以放在虚拟站点根目录(/)下,否则会死循环 如果是二级目录,如/test/,那么传入RewriteCond的参数是以/test/开始的,因此从(.+)获得的文件名也含有/test/,读者必须对此多加小心 要想仅获得文件名,可以将(.+)替换成([^/]+),并且去掉符号^,如下所示: RewriteEngine On RewriteCond %{REQUEST_FILENAME} !([^/]+)\.css$ RewriteCond %{REQUEST_FILENAME} !([^/]+)\.js$ RewriteRule ^(.+)$ /chat/ [NC]什么是User-agent?User-agent用于浏览器向服务器“自报家门”,更确切的说是所有HTTP客户端都得用User-agent向服务器“自报家门”,以便服务器对不同的客户端作出不同响应。比如,某站点可能需要对浏览器、搜索引擎crawl还有各类下载工具作出不同的响应。服务器就是通过所谓的User-agent进行区分的。 如果你的服务器提供某些资源的下载,那么你就必须多加小心诸如“迅雷”等下载软件,因为它们可能把你网站资源吸干,并且影响你的正常访客访问。为此,我们可以利用Rewrite限制某些UA的访问:
RewriteEngine on RewriteCond %{HTTP_USER_AGENT} 2.0.50727 [NC] RewriteRule . abuse.txt [L] 该规则限制“迅雷”客户端下载资源,并将下载文件重置到abuse.txt HTTP_USER_AGENT是Apache的内置变量 2.0.50727是迅雷User-agent的特征字符串 RewriteRule后面的“点”表示“任意URI”,也就是不管请求的是什么,都输出abuse.txt通常,我们不会仅限制一个UA。利用[OR]即可实现对多个UA作出统一处理:
RewriteEngine on RewriteCond %{HTTP_USER_AGENT} 2.0.50727 [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [NC,OR] # etc.. RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [NC] RewriteRule . abuse.txt [L]盗链,特别是图片,是非常可耻的!哪怕将图片复制到自己服务器上,也比盗用他人的图片链接来得光彩!(吐糟完毕) .htaccess的Rewrite功能可以提供非常简单、有效的方法阻止这种可耻行为:
RewriteEngine On RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^http://(www\.)?lesca\.me/ [NC] RewriteCond %{REQUEST_URI} !hotlink\.png [NC] RewriteRule .*\.(gif|jpg|png)$ /hotlink.png [NC]简单解释一下该规则的功能:
除本站以外其他网站都不得引用本站图片,具体可以理解为 如果引用站点为“空”或者是“本站”,或者,所引用对象是“hotlink.png”,那么就允许访问 再次提醒,RewriteCond之间默认的逻辑连接词是逻辑“与” 这里的难点是理解逻辑转换,即德·摩根定律[1] more .htaccess tips and tricks.. [2] Stupid htaccess Tricks [3] QSA Flag [4] 5 useful url rewriting examples using .htaccess
本文出自 Lesca技术宅,转载时请注明出处及相应链接。
本文永久链接: http://lesca.me/archives/htaccess-rewrite.html
0 .htaccess, rewrite