什麼是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 比對數字
\b 比對單詞的開始或結束
^ 字元串以……開始
$ 字元串以……結束
* 重複零次或更多次
+ 重複一次或更多次
? 重複零次或一次
{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