Aapache重寫規(guī)則
.htaccess叫分布式配置文件谢翎,.htaccess文件的作用在于當(dāng)瀏覽器通過uri訪問到服務(wù)器某個文件夾或文件時沾谜,我們可以決定這個uri是否訪問uri指定資源或者拒絕訪問。并且通過一個十分友好的uri吸引用戶進(jìn)來,并且通過.htaccess文件把用戶導(dǎo)向服務(wù)器指定的訪問位置。它提供了針對目錄改變配置的方法——在一個特定的文檔目錄中放置一個包含一個或多個指令的文件, 以作用于此目錄及其所有子目錄颤练。并且子目錄中的指令會覆蓋更高級目錄或者主服務(wù)器配置文件中的指令。說的通俗點,他就是:一個更改服務(wù)器配置的‘文本’文件嗦玖。一般來說患雇,如果你的虛擬主機使用的是Unix或Linux系統(tǒng),或者任何版本的Apache網(wǎng)絡(luò)服務(wù)器宇挫,從理論上講都是支持.htaccess的苛吱。他可以實現(xiàn)包括:文件夾密碼保護(hù)、用戶自動重定向器瘪、自定義錯誤頁面翠储、改變你的文件擴展名、封禁特定IP地址的用戶橡疼、只允許特定IP地址的用戶援所、禁止目錄列表,以及使用其他文件作為index文件等等欣除。
前提
必須開啟apache里面的重寫模塊住拭!
- 第一步,首先進(jìn)入apache安裝目錄下,找到httpd.conf配置文件,并打開httpd.conf驻仅。
# 找到下面這行代碼,取消其注釋符號 ‘#’谱煤。
# LoadModule reqtimeout_module libexec/apache2/mod_reqtimeout.so
第二步,找到所有的
AllowOverride denied
并改為AllowOverride all
——意思就是支持重寫禽拔。第三步刘离,重啟apache服務(wù)器。
.htaccess基本語法介紹
基本語句
語句 | 含義 |
---|---|
RewriteEngine on | 開啟apache重寫功能 |
RewriteBase / | 設(shè)置重寫根目錄 |
RewriteCond | rewrite condition 重寫條件奏赘,匹配符合條件——正則的請求 |
RewriteRule | 重定向 |
RewriteBase
RewriteEngine on
RewriteBase /
RewriteRule ^(.*)\.htm$ $1.php [R,NC,L]
RewriteBase定義了重寫基準(zhǔn)目錄寥闪。
例如太惠,如果你將虛擬站點設(shè)置在/var/www
目錄下磨淌,刪除這行將會導(dǎo)致重定向到http://yourdomain.com/var/www/1.php
。顯然這是找不到的凿渊,而且你也不會希望用戶看見你的服務(wù)器的目錄結(jié)構(gòu)梁只。
再舉個例子,如果RewriteBase /base/
埃脏,那么將會重定向到http://yourdomain.com/base/1.php
搪锣。
對于重寫基準(zhǔn)目錄,我們還可以通過將$1.php
變成/$1.php
實現(xiàn)直接變換彩掐,這時就可以將RewriteBase省略构舟。
RewriteCond說明
語法
【說明 】定義重寫發(fā)生的條件
【語法】 RewriteCond 【TestString】 【CondPattern】 [flags]
【作用域】 server config, virtual host, directory, .htaccess
【覆蓋項】 FileInfo
【狀態(tài)】 擴展(E)
【模塊】 mod_rewrite
注意事項
可以在CondPattern串的開頭使用’!'(驚嘆號)來指定不匹配。
-
CondPatterns有若干特殊的變種堵幽。除了正則表達(dá)式的標(biāo)準(zhǔn)用法狗超,還有下列用法:
‘<CondPattern’(詞典順序的小于) 將CondPattern視為純字符串弹澎,與TestString按詞典順序進(jìn)行比較。如果TestString小于CondPattern則為真努咐。 ‘>CondPattern’(詞典順序的大于) 將CondPattern視為純字符串苦蒿,與TestString按詞典順序進(jìn)行比較。如果TestString大于CondPattern則為真渗稍。 ‘=CondPattern’(詞典順序的等于) 將CondPattern視為純字符串佩迟,與TestString按詞典順序進(jìn)行比較。如果TestString等于CondPattern(兩個字符串逐個字符地完全相等)則為真竿屹。如果CondPattern是”"(兩個雙引號)报强,則TestString將與空字符串進(jìn)行比較。 ‘-d’(目錄) 將TestString視為一個路徑名并測試它是否為一個存在的目錄羔沙。 ‘-f’(常規(guī)文件) 將TestString視為一個路徑名并測試它是否為一個存在的常規(guī)文件躺涝。 ‘-s’(非空的常規(guī)文件) 將TestString視為一個路徑名并測試它是否為一個存在的、尺寸大于0的常規(guī)文件扼雏。 ‘-l’(符號連接) 將TestString視為一個路徑名并測試它是否為一個存在的符號連接坚嗜。 ‘-x’(可執(zhí)行) 將TestString視為一個路徑名并測試它是否為一個存在的、具有可執(zhí)行權(quán)限的文件诗充。該權(quán)限由操作系統(tǒng)檢測苍蔬。 ‘-F’(對子請求存在的文件) 檢查TestString是否為一個有效的文件,而且可以在服務(wù)器當(dāng)前的訪問控制配置下被訪問蝴蜓。它使用一個內(nèi)部子請求來做檢查碟绑,由于會降低服務(wù)器的性能,所以請謹(jǐn)慎使用茎匠! ‘-U’(對子請求存在的URL) 檢查TestString是否為一個有效的URL格仲,而且可以在服務(wù)器當(dāng)前的訪問控制配置下被訪問。它使用一個內(nèi)部子請求來做檢查诵冒,由于會降低服務(wù)器的性能凯肋,所以請謹(jǐn)慎使用!
-
還可以在CondPattern之后追加特殊的標(biāo)記[flags]作為RewriteCond指令的第三個參數(shù)汽馋。flags是一個以逗號分隔的以下標(biāo)記的列表:
-
‘nocase|NC’(忽略大小寫)
它使測試忽略大小寫侮东,擴展后的TestString和CondPattern中’A-Z’ 和’a-z’是沒有區(qū)別的。此標(biāo)記僅用于TestString和CondPattern的比較豹芯,而對文件系統(tǒng)和子請求的檢查不起作用悄雅。
-
‘ornext|OR’(或下一條件)
它以O(shè)R方式組合若干規(guī)則的條件,而不是隱含的AND铁蹈。
RewriteCond %{REMOTE_HOST} ^host1.* [OR] RewriteCond %{REMOTE_HOST} ^host2.* [OR] RewriteCond %{REMOTE_HOST} ^host3.* RewriteRule … 針對這3個主機的規(guī)則集 …如果不用這個標(biāo)記宽闲,你就必須要書寫三次條件/規(guī)則對。
-
RewriteRule配置參數(shù)
語句 | 含義 |
---|---|
R | 強制外部重定向;R=301 永久重定向容诬、R=302 臨時重定向 |
F | 禁止URL围辙,返回403 http狀態(tài)碼 |
G | 強制URL為GONE,返回410 http狀態(tài)碼 |
P | 強制使用代理轉(zhuǎn)發(fā) |
L | 表明當(dāng)前規(guī)則是最后一條規(guī)則放案,停止分析以后的規(guī)則重寫 |
N | 重新從第一條規(guī)則開始運行重寫過程 |
C | 與下一條規(guī)則關(guān)聯(lián) |
T=MIME-type(force MIME type) 強制MIME類型 | |
NS | 只是用于不是內(nèi)部的子請求 |
NC | 不區(qū)分大小寫 |
QSA | 追加請求字符串 |
NE | 不再輸出轉(zhuǎn)義特殊字符 %3d$1 等價于 =$1 |
生效條件
【說明 】定義重寫發(fā)生的條件
【語法】 RewriteCond 【TestString】 【CondPattern】 [flags]
【作用域】 server config, virtual host, directory, .htaccess
【覆蓋項】 FileInfo
【狀態(tài)】 擴展(E)
【模塊】 mod_rewrite
RewriteCond指令定義了規(guī)則生效的條件姚建,即在一個RewriteRule指令之前可以有一個或多個RewriteCond指令。條件之后的重寫規(guī)則僅在當(dāng)前URI與Pattern匹配并且滿足此處的條件(TestString能夠與CondPattern匹配)時才會起作用吱殉。
- RewriteRule反向引用 掸冤,引用方法是:$N (0 <= N <= 9)引用當(dāng)前(帶有若干RewriteRule指令的)RewriteCond中的與Pattern匹配的分組成分(圓括號!)。
- RewriteCond反向引用 友雳,引用方法是:%N (1 <= N <= 9)引用當(dāng)前若干RewriteCond條件中最后符合的條件中的分組成分(圓括號!)稿湿。
- RewriteMap擴展 ,引用方法是:${mapname:key|default} 細(xì)節(jié)請參見RewriteMap 指令押赊。
- 服務(wù)器變量 饺藤,引用方法是:%{NAME_OF_VARIABLE} NAME_OF_VARIABLE可以是下節(jié)apache環(huán)境變量列出的字符串之一:
apache環(huán)境變量
獲取環(huán)境變量
在上一節(jié)中講述了 %{}
代表獲取環(huán)境變量;可以獲取的環(huán)境變量中的任何變量流礁。具體內(nèi)容還需要參見官方文檔中——重寫模塊涕俗,要分析環(huán)境變量最好的方法phpinfo();訪問地址寫全一點http://www.fuermao.com/index.php?1111#111
神帅,環(huán)境變量的類型如下表(phpinfo()
所獲取的并不是特別全):
官方其他參數(shù)說明
IS_SUBREQ
如果正在處理的請求是一個子請求再姑,它將包含字符串”true”,否則就是”false”找御。模塊為了解析URI中的附加文件元镀,可能會產(chǎn)生子請求。
API_VERSION
這是正在使用中的Apache模塊API(服務(wù)器和模塊之間內(nèi)部接口)的版本霎桅, 其定義位于include/ap_mmn.h中栖疑。此模塊API版本對應(yīng)于正在使用的Apache的版本(比如在Apache 1.3.14的發(fā)行版中這個值是19990320:10)。 通常滔驶,對它感興趣的是模塊的開發(fā)者遇革。
THE_REQUEST
這是由瀏覽器發(fā)送的完整的HTTP請求行(比如:”GET /index.html HTTP/1.1″)。它不包含任何瀏覽器發(fā)送的其它頭信息瓜浸。
REQUEST_URI
這是在HTTP請求行中所請求的資源(比如上述例子中的”/index.html”)澳淑。
REQUEST_FILENAME
這是與請求相匹配的完整的本地文件系統(tǒng)的文件路徑名比原。
HTTPS
如果連接使用了SSL/TLS插佛,它將包含字符串”on”,否則就是”off”(無論mod_ssl是否已經(jīng)加載量窘,該變量都可以安全的使用)雇寇。
注意事項
SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的——即Apache服務(wù)器內(nèi)部的request_rec結(jié)構(gòu)中的filename字段。 第一個就是大家都知道的CGI變量名,而第二個則是REQUEST_URI(request_rec結(jié)構(gòu)中的uri字段)的一個副本锨侯。
特殊形式:%{ENV:variable} 嫩海,其中的variable可以是任意環(huán)境變量。它是通過查找Apache內(nèi)部結(jié)構(gòu)或者(如果沒找到的話)由Apache服務(wù)器進(jìn)程通過getenv()得到的囚痴。
特殊形式:%{SSL:variable} 叁怪,其中的variable可以是一個SSL環(huán)境變量的名字,無論mod_ssl模塊是否已經(jīng)加載都可以使用(未加載時為空字符串)深滚。比如:%{SSL:SSL_CIPHER_USEKEYSIZE}將會被替換為128奕谭。
特殊形式:%{HTTP:header} ,其中的header可以是任意HTTP MIME頭的名稱痴荐。它總是可以通過查找HTTP請求而得到血柳。比如:%{HTTP:Proxy-Connection}將被替換為Proxy-Connection:HTTP頭的值。
預(yù)設(shè)形式:%{LA-U:variable} 生兆,variable的最終值在執(zhí)行一個內(nèi)部(基于URL的)子請求后確定难捌。 當(dāng)需要使用一個目前未知但是會在之后的過程中設(shè)置的變量的時候,就可以使用這個方法鸦难。例如根吁,需要在服務(wù)器級配置(httpd.conf文件)中根據(jù)REMOTE_USER變量進(jìn)行重寫, 就必須使用%{LA-U:REMOTE_USER}合蔽。因為此變量是由URL重寫(mod_rewrite)步驟之后的認(rèn)證步驟設(shè)置的婴栽。 但是另一方面,因為mod_rewrite是通過API修正步驟來實現(xiàn)目錄級(.htaccess文件)配置的辈末, 而認(rèn)證步驟先于API修正步驟愚争,所以可以用%{REMOTE_USER}。
預(yù)設(shè)形式:%{LA-F:variable} 挤聘,variable的最終值在執(zhí)行一個內(nèi)部(基于文件名的)子請求后確定轰枝。 大多數(shù)情況下和上述的LA-U是相同的。
CondPattern是條件模式组去,即一個應(yīng)用于當(dāng)前TestString實例的正則表達(dá)式鞍陨。TestString將被首先計算,然后再與CondPattern匹配从隆。
調(diào)試重寫模塊
關(guān)于調(diào)試信息
關(guān)于調(diào)試這部分由于不能夠直接打印和輸出诚撵,所以需要在apache的日志中去查找相關(guān)信息。apache的日志大致分為兩類键闺,如:
- access_log:訪問或請求apache服務(wù)日志的訪問信息寿烟;
- error_log:apache服務(wù)器出錯時的,日志記錄錯誤信息辛燥;
日志一般都在httpd.conf
文件的相關(guān)位置有路徑筛武,當(dāng)然可以改變?nèi)罩居涗浀穆窂剑?/p>
# 錯誤日志
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here. If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
# 這個地方時我修改后的錯誤日志記錄信息位置
ErrorLog "/Users/futianyu/log/apache/error_log"
# 這個地方是日志記錄級別:一共有8個級別缝其;
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
# 暫時注釋掉
# LogLevel warn
# 重寫調(diào)試時打開,因為要調(diào)試重寫模塊
LogLevel info rewrite:trace5
#
# The location and format of the access logfile (Common Logfile Format).
# If you do not define any access logfiles within a <VirtualHost>
# container, they will be logged here. Contrariwise, if you *do*
# define per-<VirtualHost> access logfiles, transactions will be
# logged therein and *not* in this file.
# 這個地方就是訪問日志徘六,當(dāng)然我也改了路徑了内边;
CustomLog "/Users/futianyu/log/apache/access_log" common
設(shè)置日志輸出級別
此處我們需要查看的是重寫模塊調(diào)試時的錯誤信息,給個官方文檔的連接待锈;重寫模塊日志記錄中的Per-module logging部分有說明漠其;改了寫配置文件需要重啟httpd服務(wù)器,不然不會生效竿音。在上面的代碼中文檔已經(jīng)給出了日志級別的說明:debug, info, notice, warn, error, crit,alert, emerg辉懒;
示例
示例一
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$
RewriteCond %{REQUEST_URI} !^/blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /blog/$1
# 沒有輸入文件名的默認(rèn)到到首頁
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$
RewriteRule ^(/)?$ blog/index.php [L]
第一部分 重寫規(guī)則
-
RewriteEngine On
表示重寫引擎開,關(guān)閉Off谍失,作用就是方便的開啟或關(guān)閉以下的語句眶俩。
-
RewriteCond %{HTTP_HOST} \^(www\.)?xxx\.com$
RewriteCond [匹配的字符串] [正則條件]
%{}
在上面也說明了,代表獲取的系統(tǒng)變量快鱼;
這條語句表示重寫條件颠印,如果【匹配字符串】符合【正則條件】,則執(zhí)行后面的語句抹竹;
這里需要指出的是线罕,HTTP_HOST
變量是會攜帶端口號(默認(rèn)80端口是不會攜帶的),且無http://
協(xié)議格式窃判。
獲取的訪問URL中的www.xxx.com
钞楼,如果符合正則條件則,繼續(xù)執(zhí)行下面的語句袄琳。 -
`RewriteCond %{REQUEST_URI} !^/blog/``
獲取請求資源虛擬地址询件,
REQUEST_URI
是域名后至hash(#)前的部分,例如下面的網(wǎng)址:
http://www.baidu.com/aa/bb/cc.php?dd=111#ee
那么REQUEST_URI
所獲取的部分就是aa/bb/cc.php?dd=111
唆樊。
回到正題上宛琅,如果獲取到的虛擬地址信息不是以/blog/
開頭(正則前面有個!
),則執(zhí)行下面的條件逗旁; -
RewriteCond %{REQUEST_FILENAME} !-f
與RewriteCond %{REQUEST_FILENAME} !-d
這兩條語句就一起講了嘿辟,如果請求的文件不是文件,不是目錄的話片效,就執(zhí)行下面的重寫規(guī)則
RewriteRule ^(/)?$ blog/index.php [L]
红伦。 -
RewriteRule ^(.*)$ /blog/$1
這條語句是整個重寫的終點也是難點部分,意思是當(dāng)上面的RewriteCond條件都滿足的時候淀衣,將會執(zhí)行此重寫規(guī)則昙读;
^(.*)$
匹配的是當(dāng)前請求URL地址,整個地址都匹配舌缤,所以是.*
代表表示任意單個字符箕戳,*表示匹配0次或N次(N>0);后面的/blog/$1
就是重寫部分国撵,意思是將前面匹配的字符重寫成/blog/$1
陵吸。這個$1
表示反向匹配,引用的是前面第一個圓括號的成分介牙,即^(.*)
$中 的.*
壮虫。這里出現(xiàn)一個問題。
【注意】
如果請求地址是:http://www.xxx.com/a.html
环础,到底是匹配整個http://www.xxx.com/a.html
囚似,還是只匹配/a.html
即反斜杠后面的成分,還是只匹配a.html
线得?根據(jù)RewriteBase規(guī)則規(guī)定饶唤,如果Rewritebase 為
/
,將會匹配a.html
贯钩,不帶前面的反斜杠募狂,所以上條語句應(yīng)該寫成RewriteRule^(.*)$ blog/$1
(不帶/)而不是/blog/$1
。現(xiàn)在問題出來了角雷,如果不設(shè)置Rewritebase
為/
祸穷,將會匹配整個網(wǎng)址http://www.xxx.com/a.html
,顯然這是錯誤的勺三,所以應(yīng)該添加這條:RewiteBase /
雷滚。
第二部分 重寫規(guī)則
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$
-
RewriteRule ^(/)?$ blog/index.php [L]
這兩句的意思是指請求的host地址是
www.xxx.com
,如果地址的結(jié)尾只有0個或者1個“/”時吗坚,將會重寫到子目錄下的主頁祈远,主要因為重寫后的地址是不能自動尋找主頁的,需要自己指定商源。
正確答案
RewriteEngine On
RewiteBase /
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ blog/$1
# 沒有輸入文件名的默認(rèn)到到首頁
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ [NC]
RewriteRule ^(/)?$ blog/index.php [L]
示例二 將.htm頁面映射到.php
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$ $1.php [NC]
注意事項:
- 該RewriteRule能夠?qū)?htm靜態(tài)頁面映射到.php動態(tài)頁面
- 如果通過.htm進(jìn)入绊含,瀏覽器地址欄顯示的是.htm擴展名,但服務(wù)器上實際執(zhí)行的是.php
- 必須保證服務(wù)器上有對應(yīng)的.php炊汹,否則會404
- 瀏覽器和搜索引擎可以同時通過.htm和.php訪問網(wǎng)頁
- 如果該目錄上存在.htm躬充,將被忽略
- [NC]表示“不區(qū)分大小寫”,更多類似定義請參考本站《.htaccess正則表達(dá)式》一文
示例三 長短地址轉(zhuǎn)換
若訪問http://mysite/grab?file=my.zip
如何實際訪問至http://mysite/public/files/download/download.php?file=my.zip
讨便;
RewriteEngine On
RewriteRule ^grab /public/files/download/download.php
示例四 支持多域名訪問
現(xiàn)在假設(shè)你有域名domain-one.com和domain-two.com充甚,并且在服務(wù)器根目錄有對應(yīng)文件夾one和two,那么通過下面的改寫就能讓Apache同時接受者兩個域名的請求:
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]
示例五 去掉www
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]
示例六 加上www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(.*)$
RewriteRule (.*) http://www\.%1/$1 [R=301,L]
參考資料
《.htaccess 基礎(chǔ)教程(四)Apache RewriteCond 規(guī)則參數(shù)》 http://www.cnblogs.com/52php/p/5670199.html
《 .htaccess技巧: URL重寫(Rewrite)與重定向(Redirect)》 https://blog.csdn.net/newjueqi/article/details/12014673 維摩詰