什么是URL重定向:
URL重定向(URL redirection,或称网址重定向或网域名称转址),是指当使用者浏览某个网址时,将他导向到另一个网址的技术。
重写和重定向的区别:
重定向 :浏览器知道页面位置发生变化,从而改变地址栏显示的地址
搜索引擎意识到页面被移动了,从而更新搜索引擎索引,将原来失效的链接从搜索结果中移除
临时重定向(R=302)和永久重定向(R=301)都是亲搜索引擎的,是SEO的重要技术
重写:用于将页面映射到本站另一页面,若重写到另一网络主机(域名),则按重定向处理
URL重定向模块开启:
如果要想用到rewrite模块,必须先安装或加载rewrite模块。
方法有两种
一种是编译apache的时候就直接安装rewrite模块,
二是如果编译apache时以DSO模式安装apache的,可以利用源码和apxs来安装rewrite模块。
URl重定向配置方式:
1.可基于服务器级
1.1 (httpd.conf),在httpd.conf中写,这种写法适合有服务器完整权限的网站管理员,
RewriteEngine on来打开rewrite功能;
1.2 另一种是在局部virtualhost里 利用RewriteEngine on来打开rewrite功能,
需要注意的是,必须在每个virtualhost里用RewriteEngine on来打开rewrite功能。
否则virtualhost里没有RewriteEngine on它里面的规则也不会生效。
写法大概如下:
<VirtualHost *:80>
DocumentRoot "/websites/www"
ServerName localhost
RewriteEngine On
RewriteRule ^index.html$ index.php [L]
</VirtualHost>
2.目录级
(.htaccess)在网站目录中使用.htaccess,这种方法适合采用虚拟主机形式的网站管理员,
.htaccess文件可以的事情,主要包括:文件夹密码保护、用户自定义重定向、自定义404页面、扩展名伪静态化、禁止特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,等等。
修改这个配置: AllowOverride None(修改为AllowOverride All)
要注意一点那就是必须打开此目录的FollowSymLinks 符号链接属性,且在.htaccess里要声明RewriteEngine on
一些我们需要注意的地方:
FollowSymlinks必须启用,这是rewrite引擎的安全需求。
通常FollowSymlinks在Apache的主配置文件中就已经启用了,所以通常可以省略。
RewriteEngine命令用于启用rewrite引擎
IfModule命令用于判断Apache是否安装了mod_rewrite模块
mod_rewrite会处理所有提交给Apache的URL请求,并与之后的规则进行匹配
基本正则表达式:
因为URL重定向语法中大量使用了perl的正则表达式,并且正则是每隔一段时间不用都必然会淡忘的东西,所以我们有必要先回顾一下基本的正则写法:
. 匹配一个字符,(范围是换行符以外的所有字符)
w 匹配字母或数字或下划线或汉字
s 匹配任意的空白符
d 匹配数字
匹配单词的开始或结束
^ 字符串以……开始
$ 字符串以……结束
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
() $1 $2 一个括号代表一个分组,第一个括号里匹配的内容就用$1引用,第二个括号匹配的内容用$2引用,以此类推......
指令讲解:
1.重写规则的指令:
对于Rewrite来说共有九个指令:
RewriteBase,
RewriteCond,
RewriteEngine,
RewriteLock,
RewriteLog,
RewriteLogLevel,
RewriteMap,
RewriteOptions,
RewriteRule。
通常最常用的是 RewriteEngine, RewriteBase, RewriteCond, RewriteRule 四个指令,
下面简单介绍这四个指令。
RewriteEngine: 就是是否使用 Rewrite 模式的开关, 使用就设置成 on, 否则设置成 off。
RewriteBase:设置了目录级重写的基准URL,RewriteBase 的作用域为: directory, .htaccess
多数网站URL不是直接对应于其物理文件路径的,在这种情况下,
就必须用RewriteBase指令来指定正确的URL前缀。
通常默认的虚拟主机的网站在使用.htaccess 进行重写规则时不需要执行设置该指令.
因为 RewriteBase 默认值是该 .htaccess 文件所在的目录地址.
但是如果使用目录别名的话就需要设置这个指令了,例如 alias
举个例子,如果将1.html 重定向为1.php 设置为 RewriteBase /base/,
那么将会重定向到http://yourdomain.com/base/1.php。
对于重写基准目录,我们还可以通过将$1.php变成/$1.php实现直接变换,这时就可以将RewriteBase省略。
如果重定向到新的主机地址(域名),RewriteBase也就没有出现的必要了。
RewriteCond:指令定义一条规则条件。
在一条RewriteRule指令前面可能会有一条或多条RewriteCond指令,
只有当自身的模板(pattern)匹配成功且这些条件也满足时规则才被应用于当前URL处理。
注意,RewriteCond 指令后面可带 Flag, 现在只要2个可用,
一个是 NC(不区分大小写的意思), 一个是 OR(连接下一个条件)。
RewriteRule:是一个简单的命令告诉mod_rewrite这个模块如何去重写,
关键的地方在于可以在模式和替换中使用正则表达式来匹配相应的字符,
正则表达式的广泛的灵活性能将动态的URL转换成各式各样的符合要求的静态URL
格式: RewriteRule Pattern Substitution [flags]
在URL重写的匹配部分中, 服务器会把请求的URL的一部分删除掉,再传递给Pattern部分进行匹配.
重写结束后再添加上去.
所有平常我们看到的匹配规则总是不带网址前面的那些域名的什么东西的. 也不带什么目录什么的.
这些 apache已经给删掉了. 处理完后再加到前面。
但是有个例外就是如果 Substitution 部分是带 http:// 开头的话, 那就直接重定向了. 服务器不会把先前删除的再给加上了. 不然就出错了。
Apache Rewrite规则修正符 :
R 强制外部重定向 redirect|R [=code] (强制重定向 redirect)
例如: [R=301,L] 永久重定向; [R=302,L] 临时重定向;R默认为302
F 禁用URL,返回403HTTP状态码。
G 强制URL为GONE,返回410HTTP状态码。
P 强制使用代理转发。
L 表明当前规则是最后一条规则,停止分析以后规则的重写。
N 重新从第一条规则开始运行重写过程。
C 与下一条规则关联
2.服务器变量
NAME_OF_VARIABLE 具体数值见下表:
HTTP_USER_AGENT //主要用于检测访问者系统和浏览器等
HTTP_REFERER //从哪个页面链接过来
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST //取请求的域名 例如:www.test.com;不包括“http://”和“ /”
REQUEST_URI //这是在HTTP请求行中所请求的资源。例如:/share77.html
相对地址,就是相对根目录的地址,就是域名/后面的成分,格式上包括最前面的“/”
REQUEST_FILENAME //这是与请求相匹配的完整的本地文件系统的文件路径名或描述.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
这两句语句的意思是请求的文件或路径是不存在的,
如果文件或路径存在将返回已经存在的文件或路径
HTTP_PROXY_CONNECTION
HTTP_ACCEPT
REMOTE_ADDR
REMOTE_HOST
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPE
DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_ADDR
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIME
API_VERSION //这是正在使用的httpd中(服务器和模块之间内部接口)的Apache模块API的版本,
其定义位于include/ap_mmn.h中。此模块版本对应于正在使用的Apache的版本
(比如,在Apache 1.3.14的发行版中,这个值是19990320:10)。
通常,对它感兴趣的是模块的作者。
THE_REQUEST //这是由浏览器发送给服务器的完整的HTTP请求行。
(比如, “GET /index.html HTTP/1.1″). 它不包含任何浏览器发送的附加头信息。
IS_SUBREQ //如果正在处理的请求是一个子请求,它包含字符串”true”,否则就是”false”。
模块为了解析URI中的附加文件,有可能会产生子请求。
实例分析:
1.重写,只对域名后的资源进行修改
RewriteRule ^/$ /about/ [R]
http://www.xxx.cn/index.html -> http://www.xxx.cn/index.php
RewriteRule index.html index.php
http://www.xxx.cn/test8.html -> http://www.xxx.cn/test.php?id=8 (这个也叫伪静态)
RewriteRule ^test([0-9]*).html$ test.php?id=$1
http://www.xxx.cn/cat-1-3.html -> http://www.xxx.cn/cat.php?id1=1&id2=3
RewriteRule ^cat-([0-9]+)-([0-9]+).html$ cat.php?id1=$1&id2=$2
前面第一个()中匹配的内容后面就用$1引用,第二个()中匹配的就用$2应用……
将.htm页面映射到.php:
RewriteRule ^(.*).htm$ $1.php [NC]
注意事项:
该RewriteRule能够将.htm静态页面映射到.php动态页面
如果通过.htm进入,浏览器地址栏显示的是.htm扩展名,但服务器上实际执行的是.php
[NC]表示“不区分大小写”
增加一个R标识符,重写即变为重定向:
RewriteRule ^(.*).htm$ $1.php [R,NC,L]
注意事项:
该RewriteRule能够将.htm静态页面重定向到.php动态页面
如果通过.htm进入,浏览器地址栏会自动转为.php,这也是重定向的本质
2..基于域名的重定向
当访问163.com时 跳转到www.163.com
RewriteCond %{HTTP_HOST} ^163.com [NC]
RewriteRule ^(.*) http://www.163.com$1 [R=301,L]
当访问这个70.40.213.183 开头的ip时,跳转到www.163.com域名
RewriteCond %{HTTP_HOST} ^70.40.213.183 [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^(.*) http://www.163.com/ [L]
#声明Client请求的主机中前缀是70.40.213.183, [NC] 的意思是忽略大小写
#声明Client请求的主机中前缀不为空
#[L]意味着立即停止重写操作,并不再应用其他重写规则。
。
又跨域,又要url不变的重定向
我们可以用以下方法解决:(这样浏览器中的url没有变化 , 但是内容已经是sina的了)
RewriteRule /66.htm$ http://www.sina.com.cn [P]
RewriteRule /66.htm$ http://127.0.0.1:8080/sohu/sd.jsp [P]
注意:这里的P是代理模式转发,必须用url全称,并且要保证modProxy打开,也就是下面httpd.conf中的着两句:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
如果不打开则会出现403禁止页面。
1、图片重定向
RewriteEngine On
RewriteCond %{HTTP_HOST} ^localhost$ //如果域名是localhost
RewriteCond %{REQUEST_FILENAME} !-f //并且访问的文件找不到
RewriteRule ^images/(.+) http://127.0.0.1/test/showimages/$1 [R=302,L]
//则跳转到另一个域名下的另一个目录访问这个图片
当请求不存在的资源时, 统一定义到根目录下的 404.html
文件名不存在、目录不存在、跳转404页面
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /404.html [L]
限制访问. 比如来自一些不友好的网站连接过来的请求. 不允许访问.
下例中如果 HTTP_REFERER 中包含 sex 字符, 则不允许访问.
RewriteCond %{HTTP_REFERER} sex
RewriteRule ^.*$ - [F]
伪静态化, 比如访问 /user20.html 则调用viewUser.php 显示用户ID为20的用户资料
RewriteRule ^user([0-9]*).html$ viewUser.php?userid=$1
喜欢用二级域名的比较实用了. 比如网站目录下有 user, upload 等几个目录,
可以通过 http://www.test.com/user 这样的模式访问.
但是如果想做成统一用二级域名模式访问: http://user.test.com , 但是不允许 http://www.test.com/user 这样访问.
那么就像下面这样来限制.
RewriteCond %{REQUEST_URI} ^/user
RewriteRule ^.*$ http://user.test.net" [L]
防止图片盗链
RewriteEngine On
RewiteBase /
RewriteCond %{HTTP_REFERER} !^http://(.+.)?baidu.com/ [NC] //如果来源网址不是*.baidu.com
RewriteCond %{HTTP_REFERER} !^$ //并且来源网址不是空
RewriteRule .*.(jpe?g|gif|bmp|png)$ /images/nohotlink.jpg [L] //如果访问的文件后缀是jpeg,jpg,gif,bmp,png的图片,则重定向到一个固定的图片
我们使用 .htaccess 来定义重写规则. 假设域名为: www.test.com
.htaccess 放在网站根目录下. 比如: /.htaccess
例子1: 所有请求都定向到 index.php 脚本, 注意要排除 index.php 本身. 比如就进入死循环了.
RewriteRule !^index.php$ index.php [L]
例子2: 按照时间显示不同的页面, 比如访问 hello.html 页面时.
如果 在 8:00-19:00 的时候访问. 显示 hello.day.html 其他时间访问显示: hello.night.html
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule ^hello.html$ hello.day.html
RewriteRule ^hello.html$ hello.night.html
官方的例子: 重写规则写在 httpd.conf 文件里. 请求地址为: http://www.test.com/somepath/pathinfo,
看下面几种结果. Given Rule => Resulting Substitution
-------------------------------------------------------------------------------
^/somepath(.*) otherpath$1 => 不支持, 无效的重写语句
^/somepath(.*) otherpath$1 [R] => 不支持, 无效的重写语句
^/somepath(.*) otherpath$1 [P] => 不支持, 无效的重写语句
-------------------------------------------------------------------------------
^/somepath(.*) /otherpath$1 => /otherpath/pathinfo
^/somepath(.*) /otherpath$1 [R] => http://www.test.com/otherpath/pathinfo 外部重定向
^/somepath(.*) /otherpath$1 [P] => 不支持, 很傻.
-------------------------------------------------------------------------------
^/somepath(.*) http://www.test.com/otherpath$1 => /otherpath/pathinfo
^/somepath(.*) http://www.test.com/otherpath$1 [R] => http://www.test.com/otherpath/pathinfo 外部重定向
^/somepath(.*) http://www.test.com/otherpath$1 [P] => 不支持, 很傻.
---------------------------------------------- ----------------------------------
^/somepath(.*) http://www.xxx.com/otherpath$1 => http://www.xxx.com/otherpath/pathinfo 外部重定向
^/somepath(.*) http://www.xxx.com/otherpath$1 [R] => http://www.xxx.com/otherpath/pathinfo 外部重定向 [R] 多余.
^/somepath(.*) http://www.xxx.com/otherpath$1 [P] => http://www.xxx.com/otherpath/pathinfo 内部网关重定向
同样的请求上面的地址, 如果在 .htaccess 文件里的写法. 注意和 httpd.conf 写法的区别.
比如 .htaccess 文件在目录一个虚拟主机的根目录下.
然后请求 http://www.test.com/localpath/pathinfo 看下面的几种结果.
Given Rule => Resulting Substitution
-------------------------------------------------------------------------------
^localpath(.*) otherpath$1=> /otherpath/pathinfo
^localpath(.*) otherpath$1 [R] => http://www.test.com/otherpath/pathinfo 外部重定向
^localpath(.*) otherpath$1 [P] => 不支持, 很傻.
-------------------------------------------------------------------------------
^localpath(.*) /otherpath$1 => /otherpath/pathinfo 注意 /otherpath$1 和 otherpath$1 的区别
^localpath(.*) /otherpath$1 [R] => http://www.test.com/otherpath/pathinfo 外部重定向
^localpath(.*) /otherpath$1 [P] => 不支持, 很傻.
-------------------------------------------------------------------------------
^localpath(.*) http://www.test.com/otherpath$1 /otherpath/pathinfo
^localpath(.*) http://www.test.com/otherpath$1 [R] http://www.test.com/otherpath/pathinfo 外部重定向
^localpath(.*) http://thishost/otherpath$1 [P] => 不支持, 很傻.
-------------------------------------------------------------------------------
^localpath(.*) http://www.test.com/otherpath$1 => http://www.test.com/otherpath/pathinfo 外部重定向
^localpath(.*) http://www.xxx.com/otherpath$1 [R] => http://www.xxx.com/otherpath/pathinfo 外部重定向 [R] 可省略
^localpath(.*) http://www.xxx.com/otherpath$1 [P] => http://www.xxx.com/otherpath/pathinfo 内部网关重定向
Apache重写规则的常见应用(rewrite)
一:目的
本文旨在提供怎么用Apache重写规则来解决一些常见的URL重写方法的问题,通过常见的
实例给用户一些使用重写规则的基本方法和线索。
二:为什么需要用重写规则?
一个网站,如果是长期需要放在internet上提供服务,必定会有不断地更新和维护,如临
时转移到其他服务器进行维护,重新组织目录结构,变换URL甚至改动到新的域名等等,
而为了让客户不会因此受到所有影响,最佳的方法就是使用Apache Rewrite Rule(重写
规则)。
三: 重写规则的作用范围
1) 能使用在Apache主设置文件httpd.conf中
2) 能使用在httpd.conf里定义的虚拟主机设置中
3) 能使用在基本目录的跨越设置文件.htaccess中
四:重写规则的应用条件
只有当用户的WEB请求最终被导向到某台WEB服务器的Apache后台,则这台WEB服务器接受
进来的请求,根据设置文件该请求是主设置还是虚拟主机,再根据用户在浏览器中请求的
URI来配对重写规则并且根据实际的请求路径配对.htaccess中的重写规则。最后把请求
的内容传回给用户,该响应可能有两种:
1) 对浏览器请求内容的外部重定向(Redirect)到另一个URL。
让浏览器再次以新的URI发出请求(R=301或R=302,临时的或是永久的重定向)
如:一个网站有正规的URL和别名URL,对别名URL进行重定向到正规URL,或网站改换
成了新的域名
则把旧的域名重定向到新的域名(Redirect)
2) 也可能是由Apache内部子请求代理产生新的内容送回给客户[P,L]
这是Apache内部根据重写后的URI内部通过代理模块请求内容并送回内容给客户,而客户
端浏览器并不知道,浏览器中的URI不会被重写。但实际内容被Apache根据重写规则后的URI得到。
如:在公司防火墙上运行的Apache启动这种代理重写规则,代理对内部网段上的WEB服务
器的请求。
五:重写规则怎样工作?
我们假定在编译Apache时已把mod_rewrite编译成模块,确信你的httpd.conf中有
LoadModule rewrite_module libexec/mod_rewrite.so
并且在Addmodule中有 Addmodule mod_rewrite.c则能使用重写规则。
当外部请求来到Apache,Apache调用重写规则中的定义来重写由用户浏览器指定请求的
URI,最后被重写的URI如果是重定向,则送由浏览器作再一次请求;如果是代理则把重写
后的URI交给代理模块请求最终的内容(Content),最后把内容送回给浏览器。
六: 何时使用.htaccess中的重写规则定义?
如果你对你的的网站内容所在的服务器没有管理员权限,或你的网站放在ISP的服务器
上托管等等条件下,你无法改写主设置文件,然而你能对你的WEB站点内容所在的目录
有写权限,则你能设置自己的.htaccess
文件达到同样的目的。但你需要确定主设置文件中对你的网站所在的目录定义了下面的内
容:
Options Indexes FollowSymLinks
AllowOverride all
否则你的.htaccess不会工作。
七: 应用举例
假定Apache被编译安装在主机192.168.1.56的/usr/local/apache/ 目录下面,我们编
译进了重写和代理模块。
1) 隐藏Apache下的某个目录,使得对该目录的所有请求都重定向到另一个文件。
a> httpd.conf的实现方法
我们放下面的部分到/usr/local/apache/conf/httpd.conf
options Indexes followsymlinks
allowoverride all
rewriteengine on
rewritebase /
rewriterule ^(.*)$ index.html.en [R=301]
注:rewriteengine on 为重写引擎开关,如果设为off,则所有重写规则定义将不被应
用,该开关的另一好处就是如果为了临时拿掉重写规则,则改为off再重启动Apache即
可,不必将下面一条条的重写规则注释掉。
rewritebase / 的作用是如果在下面的rewriterule定义中被重写后的部分(此处为文件
名index.html.en)前面没有/,则是相对目录,相对于这个rewritebase后面的定义也就
是/usr/local/apache/htdocs/index.html.en,否则,如果此处没有rewritebase /这
一项,则被重写成
http://192.168.1.56/usr/local/apache/htdocs/manual/index.html.en ,显然是
不正确的。
不过这里我们也能不用rewritebase / , 而改为
rewriteengine on
rewriterule ^(.*)$ /index.html.en [R=301]
或
rewriteengine on
rewriterule ^(.*)$ http://192.168.1.56/index.html.en [R=301]
b> .htaccess的实现方法
我们先放下面的部分到httpd.conf
options Indexes followsymlinks
allowoverride all
然后放下面的部分到/usr/local/apache/htdocs/manual/.htaccess中
rewriteengine on
rewritebase /
rewriterule ^(.*)$ index.html.en [R=301]
注:对文件.htaccess所作的所有改动不必重启动Apache.
问:要是把这个manual目录重定向到用户jephe的自己的主目录呢?
用下面的.htaccess方案。
rewriteengine on
rewritebase /~jephe/
rewriterule ^(.*)$ $1 [R=301]
则对manual目录下所有文件的请求被重定向到~jephe目录下相同文件的请求。
2) 转换www.username.domain.com的对于username的主页请求为
www.domain.com/username
对于HTTP/1.1的请求包括一个Host: HTTP头,我们能用下面的规则集重写
http://www.username.domain.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
注:
rewritecond 条件重写规则,当满足后面定义的条件后才会应用下面的重写规则,
rewritecond有各种变量
,请查阅相关文件。
3) 防火墙上的重写规则代理内部网段上服务器的请求。
NameVirtualhost 1.2.3.4
servername www.domain.com
rewriteengine on
proxyrequest on
rewriterule ^/(.*)$ http://192.168.1.3/$1 [P,L]
注:当外部浏览器请求www.domain.com时被解析到IP地址1.2.3.4 ,Apache 交出
mod_rewrite处理转换成
http://192.168.1.3/$1后再交由代理模块mod_proxy得到内容后传送回用户的浏览器。
4) 基本预先设定的转换MAP表进行重写 rewritemap
转换www.domain.com/{countrycode}/anypath 到Map表中规定的URI,上面是虚拟主机
中的定义
rewritelog /usr/local/apache/logs/rewrite.log
rewriteloglevel 9
rewriteengine on
proxyrequest on
rewritemap sitemap txt:/usr/local/apache/conf/rewrite.map
rewriterule ^/([^/]+)+/(.*)$ http://%{REMOTE_HOST}::$1 [C]
rewriterule (.*)::([a-z]+)$ ${sitemap:$2|http://h.i.j.k