`
hehailin1986_163.com
  • 浏览: 151041 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Apache2.2 初级URL重写指南(RewriteRule)

    博客分类:
  • PHP
阅读更多
原文地址:
http://blog.ixpub.net/html/18/9727518-68873.html

规范化URL

描述:
在有些web服务器上,一个资源会拥有多个URL。在实际应用和发布中应该使用的是规范的URL,其他的则是简写或者只在内部使用。无论用户在请求中使用什么形式的URL,最终看见的都应该是规范的URL。
解决方案:
对所有不规范的URL执行一个外部HTTP重定向,以改变它在浏览器地址栏中的显示及其后继请求。下例中的规则集用规范的/u/user替换/~user,并修正了/u/user所遗漏的后缀斜杠。

RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R]
RewriteRule ^/([uge])/([^/]+)$ /$1/$2/ [R]

规范化主机名

描述:
这个规则的目的是强制使用特定的主机名以代替其他名字。比如,你想强制使用www.example.com代替example.com,就可以在以下方案的基础上进行修改:
解决方案:

对运行在非80端口的站点

RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{SERVER_PORT} !^80$
RewriteRule ^/(.*)http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]

对运行在80端口的站点

RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*)http://fully.qualified.domain.name/$1 [L,R]

移动过的DocumentRoot

描述:
通常,web服务器的DocumentRoot直接对应于URL"/",但是它常常不是处于最高的一级。比如,你希望访问者在进入网站时首先进入/about/目录。可以使用下面给出的规则集。
解决方案:
只需将"/"重定向到"/about/"即可:

RewriteEngine on
RewriteRule ^/$ /about/ [R]

也可以使用RedirectMatch指令解决问题:

RedirectMatch ^/$http://example.com/e/www/

结尾斜杠问题

描述:
每个网管对引用目录的结尾斜杠问题都有一本苦经,如果遗漏了,服务器会产生一个错误,因为如果请求是"/~quux/foo"而不是"/~quux/foo/",服务器就会去找一个叫foo的文件,而它是一个目录,所以就报错了。通常,可以使用这个FAQ entry里面提到的方法解决问题。但是有时候需要使用重写规则来解决问题,比如,在应用了许多复杂的重写规则之后。
解决方案:
解决这个微妙问题的方案是让服务器自动添加后缀斜杠。为了达到目的,必须使用一个外部重定向,以使浏览器能够正确地处理后继的请求(比如对图片的请求)。如果仅仅执行一个内部重写,可能仅仅对目录页面有效,而对含有相对URL的图片的页面无效,因为浏览器有请求内嵌目标的可能。比如,如果不用外部重定向,对/~quux/foo/index.html页面中的image.gif的请求将变成对/~quux/image.gif的请求!所以,应该这样写:

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo$ foo/ [R]

又懒又疯狂的做法是把这些写入其宿主目录中的顶级.htaccess中:

RewriteEngine on
RewriteBase /~quux/
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R]

但是这样一来会增加处理上的开销。

将用户主目录移动到不同web服务器

描述:
通常,许多网管在建立一个新的web服务器时,都会有这样的要求:重定向一个web服务器上的所有用户主目录到另一个web服务器。
解决方案:
很简单,在老的web服务器上重定向所有的"/~user/anypath"到"http://newserver/~user/anypath":

RewriteEngine on
RewriteRule ^/~(.+) http://newserver/~$1 [R,L]

在多个目录中搜索页面

描述:
有时会有必要使web服务器在多个目录中搜索页面,对此,MultiViews或者其他技术无能为力。
解决方案:
编制一个明确的规则集以搜索目录中的文件:

RewriteEngine on

# 首先尝试在 dir1 中寻找,找到即停
RewriteCond /your/docroot/dir1/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir1/$1 [L]

# 然后尝试在 dir2 中寻找,找到即停
RewriteCond /your/docroot/dir2/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir2/$1 [L]

# 再找不到就继续寻找其他的 Alias 或 ScriptAlias 目录
RewriteRule ^(.+) - [PT]

按照URL的片段设置环境变量

描述:
希望保持请求之间的状态信息,又不希望使用CGI来包装所有页面,只是通过分离URL中的有用信息来做到。
解决方案:
可以用一个规则集来分离出状态信息,并设置环境变量以备此后用于XSSI或CGI。这样,一个"/foo/S=java/bar/"的URL会被解析为"/foo/bar/",而环境变量STATUS则被设置为"java"。

RewriteEngine on
RewriteRule ^(.*)/S=([^/]+)/(.*) $1/$3 [E=STATUS:$2]

虚拟用户主机

描述:
如果需要为用户username支持一个www.username.host.domain.com的主页,但不在此机器上建虚拟主机,而是仅用在此机器上增加一个DNS A记录的方法实现。
解决方案:
仅能对包含"Host: "头的HTTP/1.1请求实现。可以使用以下规则集内部地将http://www.username.host.com/anypath重写为/home/username/anypath

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.[^.]+\.host\.com$
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ^www\.([^.]+)\.host\.com(.*) /home/$1$2

为外来访问者重定向用户主目录

描述:
对不是来自本地域ourdomain.com的外来访问者的请求,重定向其用户主目录URL到另一个web服务器www.somewhere.com,有时这种做法也会用在虚拟主机的配置段中。
解决方案:
只须一个重写条件:

RewriteEngine on
RewriteCond %{REMOTE_HOST} !^.+\.ourdomain\.com$
RewriteRule ^(/~.+)http://www.somewhere.com/$1 [R,L]

重定向锚

描述:
默认情况下,重定向到一个HTML锚是不可行的,因为'#'会被转义为'%23'。This, in turn, breaks the redirection.
解决方案:
在RewriteRule指令中使用[NE]标志(不转义)。

依赖于时间的重写

描述:
在页面内容需要按时间的不同而变化的场合,比如重定向特定页面等,许多网管仍然采用CGI脚本的方法,如何用mod_rewrite来实现呢?
解决方案:
有许多名为TIME_xxx的变量可以用在重写条件中,联合使用词典模式的"<STRING", "=STRING", ">STRING"比较,就可以实现依赖于时间的重写:

RewriteEngine on
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule ^foo\.html$ foo.day.html
RewriteRule ^foo\.html$ foo.night.html

此例使foo.html在07:00-19:00时间内指向foo.day.html,而在其余时间指向foo.night.html,对主页是一个不错的功能...

对YYYY转变为XXXX的向前兼容

描述:
在转变了大批document.YYYY文件为document.XXXX后(比如.html→.phtml),如何保持URL的向前兼容(仍然虚拟地存在)?
解决方案:
只须按基准文件名重写,并测试带有新的扩展名的文件是否存在,如果存在则用新的,否则仍然用原来的。

# 将document.html重写为document.phtml的向后兼容的规则集
# 当且仅当document.phtml存在且document.html不存在的时候
RewriteEngine on
RewriteBase /~quux/
# 剪切并记住basename
RewriteRule ^(.*)\.html$ $1 [C,E=WasHTML:yes]
# 如果存在的话就重写为document.phtml
RewriteCond %{REQUEST_FILENAME}.phtml -f
RewriteRule ^(.*)$ $1.phtml [S=1]
# 否则返回先前的basename
RewriteCond %{ENV:WasHTML} ^yes$
RewriteRule ^(.*)$ $1.html

内容处理
从旧到新(内部)

描述:
假定已经把文件foo.html改名为bar.html,需要对老的URL向后兼容,即让用户仍然可以使用老的URL,而感觉不到文件被改名了。
解决方案:
通过以下规则内部地将老的URL重写为新的:

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ bar.html

从旧到新(外部)

描述:
仍然假定已经把文件foo.html改名为bar.html,需要对老的URL向后兼容,但是要让用户得到文件被改名的暗示,即浏览器的地址栏中显示的是新的URL。
解决方案:
作一个HTTP的强制重定向以改变浏览器和用户界面上的显示:

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ bar.html [R]

从静态到动态

描述:
如何无缝转换静态页面foo.html为动态的foo.cgi,而不为浏览器/用户所察觉。
解决方案:
只须重写此URL为CGI-script,并强制作为CGI-script运行的MIME类型。比如对/~quux/foo.html的请求会执行/~quux/foo.cgi 。

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ foo.cgi [T=application/x-httpd-cgi]


访问控制
阻止Robot

描述:
如何阻止一个完全匿名的Robot取得特定网络区域的页面?/robots.txt文件可以包含若干"Robot排除协议"行,但不足以阻止此类Robot。
解决方案:
可以用一个规则集以拒绝对网络区域/~quux/foo/arc/(对一个很深的目录区域进行列表可能会使服务器产生很大的负载)的访问。还必须确保仅阻止特定的Robot,也就是说,仅仅阻止Robot访问主机是不够的(这样会同时阻止用户访问该主机)。为此,就需要对HTTP头的User-Agent信息作匹配。

RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$
RewriteRule ^/~quux/foo/arc/.+ - [F]

阻止内嵌的图片

描述:
假设http://www.quux-corp.de/~quux/有一些内嵌GIF图片的页面,这些图片很好,所以就有人盗链到他们自己的页面中了。由于这样徒然增加了我们服务器的流量,因此,我们不愿意这种事情发生。
解决方案:
虽然,我们不能100%地保护这些图片不被写入别人的页面,但至少可以对发出HTTP Referer头的浏览器加以限制。

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
RewriteRule .*\.gif$ - [F]

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$
RewriteRule ^inlined-in-foo\.gif$ - [F]

拒绝代理

描述:
如何拒绝某个主机或者来自特定主机的用户使用Apache代理?
解决方案:
首先,要确保在配置文件中mod_rewrite位于mod_proxy之后!使它在mod_proxy之前被调用。然后,使用如下方法拒绝某个主机:

RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* - [F]

使用如下方法拒绝user@host-dependent用户:

RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^badguy@badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* - [F]

其它
外部重写引擎

描述:
如何解决似乎无法用mod_rewrite解决的FOO/BAR/QUUX/之类的问题?
解决方案:
可以使用一个与RewriteMap功能相同的外部RewriteMap程序,一旦它在Apache启动时被执行,则从STDIN接收被请求的URL ,并将处理过(通常是重写过的)的URL(以相同顺序)在STDOUT输出。

RewriteEngine on
RewriteMap quux-map prg:/path/to/map.quux.pl
RewriteRule ^/~quux/(.*)$ /~quux/${quux-map:$1}

#!/path/to/perl

# 禁止使用会导致Apache陷入死循环的I/O缓冲
$| = 1;

# 从stdin读取URL(每行一个),并在stdout输出替换URL
while (<>) {
s|^foo/|bar/|;
print $_;
}

这是只是一个简单的示例,只是把所有的/~quux/foo/...重写为/~quux/bar/...而已。但事实上,可以把它修改成任何你想要的输出。但是要注意,虽然一般用户都可以使用,可是只有系统管理员才可以定义这样的映射。
分享到:
评论

相关推荐

    Url重写篇视频------本讲将通过实例比较ASP.NET下的三种典型URL重写方案

    本讲将通过实例比较ASP.NET下的三种典型URL重写方案——ISAPI重写(使用开源组件IIRF),ASP.NET2.0内置的urlMappings和基于自定义HTTPModule的URL重写(使用NBear.Web中的UrlRewriteModule实现),并探讨URL重写中...

    url 重写(伪静态)

    地址重写——简单实现/去掉问号 2. 地址重写——无扩展名/任意扩展名 3. 地址重写——404检测 4. 地址重写——封IP 5. 地址重写——字符串转换器的应用 6. 地址重写——静态映射的应用 进阶篇 1. 创建并...

    ThinkPHP的URL重写问题

    我想要的结果无非是去掉URL路径中的index.php 首先是配置.htaccess RewriteEngine on ...因为我部署在apache上面,需要httpd.conf配置文件中找到LoadModule rewrite_module modules/mod_rewrite.so去掉前面的

    asp伪静态化/asp静态化/ASPURL重写/IIS Rewrite/RewriteRule/

    asp伪静态化/asp静态化/ASPURL重写/IIS Rewrite/RewriteRule/

    Apache之Rewrite和RewriteRule规则梳理以及http强转https的配置总结(完整版)

    本篇文章详细介绍了Apache之Rewrite和RewriteRule规则以及http强转https的配置总结,可作为平时运维手册.特此分享,希望能帮助到有用到的朋友!

    zencart静态SEO URL重写插件3.6.3

    6、添加url重写规则.htaccess 1)如果网站安装在域名根目录,那么在网店安装文件夹下,新建立一个.htaccess文件,加上以下代码: RewriteEngine On # Don't rewrite any URIs ending with a file extension ...

    APACHE_RewriteRule

    APACHE_RewriteRule详细说明

    IIS服务器SSI(rewrite重写)插件的帮助资料

    ISAPI_Rewrite 是一款适用于IIS的功能强大的基于正则表达式的URL处理模块。它兼容Apache的mod_rewrite的语法,从而使仅仅复制.htaccess文件就把配置从appach移植到IIS中或者从IIS移值到appach中变成可能。请参阅3.2...

    关于Apache_mod_rewite的中文配置和RewriteRule规则详细介绍

    关于Apache_mod_rewite的中文配置和RewriteRule规则详细介绍

    浅谈ThinkPHP的URL重写

    我想要的结果无非是去掉URL路径中的index.php 首先是配置.htaccess 复制代码 代码如下: RewriteEngine on ...因为我部署在apache上面,需要httpd.conf配置文件中找到LoadModule rewrite_module modules/mod_rewr

    apache rewrite规则实现白名单

     正则找出不是六个文件的URL的模式,进行过滤。 对比同事的结果,自己思路的问题:  1. 想找出所有不符合规则的,越想越多,无法下手。—————- 思路错误,应该 制定白名单,  2. 概念错误, 弄错 REQUEST_...

    apache反向代理

    在上面的虚拟主机重写规则中,重写后的URL与您所请求的URL是一样的,我们的设想是将下面3个域名放到防火墙的/etc/hosts文件中,这样Apache将从内部3台Web服务器获得内容,并返回给外部用户,域名对应记录如下。...

    apache rewrite rule

    apache rewrite rule: 介绍详细

    Apache2.4 Win64位

    apache No input filespecified,今天是我们配置apache RewriteRule时出现这种问题,解决办法很简单如下 打开.htaccess 在RewriteRule 后面的index.php教程后面添加一个“?” 完整代码如下 .htaccess ...

    apache 二级域名解析实现方法

    RewriteEngine on RewriteMap lowercase int:tolower RewriteMap vhost txt:/usr/local/etc/apache/vhost.map RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$ RewriteCond ${vhost:%1} ^(/.*)$ RewriteRule ^/(.*...

    apache_rewrite_tester:为你的 apache 重写规则编写单元测试,brah

    apache_rewrite_tester 为您的 Apache 重写规则编写单元测试,呵呵。 这显然只是一个徒劳的练习,但它恰好是一个非常有教育意义的徒劳练习。 不要指望这与 Apache 的任何特质相匹配。

    php快速url重写 更新版[需php 5.30以上]

    对于apache的rewrite模块打开和设置则非本文主题,请见其他文章详解. 这个类只能php 5.30以上的版本才能使用,继承了上一个版本的快速重定向的特点(单独类,全部使用静态调用),增添了一个很重要的功能和属性 可以调用...

    php快速url重写更新版[需php 5.30以上]

    对于apache的rewrite模块打开和设置则非本文主题,请见其他文章详解. 这个类只能php 5.30以上的版本才能使用,继承了上一个版本的快速重定向的特点(单独类,全部使用静态调用),增添了一个很重要的功能和属性 可以调用...

    Apache RewriteBase 指令使用介绍

    RewriteBase用于设定重写的基准URL。在下文中,你可以看见RewriteRule可以用于目录级的配置文件中 (.htaccess)并在局部范围内起作用,即规则实际处理的只是剥离了本地路径前缀的一部分。处理结束后,这个路径会被...

Global site tag (gtag.js) - Google Analytics