http://www.cnblogs.com/adforce/archive/2012/11/23/2784664.htmlphp
.htaccess是什麼
.htaccess文件(或者"分佈式配置文件")提供了針對目錄改變配置的方法, 即,在一個特定的文檔目錄中放置一個包含一個或多個指令的文件, 以做用於此目錄及其全部子目錄。做爲用戶,所能使用的命令受到限制。管理員能夠經過Apache的AllowOverride指令來設置。
概述來講,htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置。經過htaccess文件,能夠幫咱們實現:網頁301重定向、自定義404錯誤頁面、改變文件擴展名、容許/阻止特定的用戶或者目錄的訪問、禁止目錄列表、配置默認文檔等功能。
啓用.htaccess,須要修改httpd.conf,啓用AllowOverride,並能夠用AllowOverride限制特定命令的使用。若是須要使用.htaccess之外的其餘文件名,能夠用AccessFileName指令來改變。例如,須要使用.config ,則能夠在服務器配置文件中按如下方法配置:AccessFileName .config 。
籠統地說,.htaccess能夠幫咱們實現包括:文件夾密碼保護、用戶自動重定向、自定義錯誤頁面、改變你的文件擴展名、封禁特定IP地址的用戶、只容許特定IP地址的用戶、禁止目錄列表,以及使用其餘文件做爲index文件等一些功能。
工做原理
.htaccess文件(或者"分佈式配置文件")提供了針對每一個目錄改變配置的方法,即在一個特定的目錄中放置一個包含指令的文件,其中的指令做用於此目錄及其全部子目錄。
說明:
若是須要使用.htaccess之外的其餘文件名,能夠用AccessFileName指令來改變。例如,須要使用.config ,則能夠在服務器配置文件中按如下方法配置:
AccessFileName .config
一般,.htaccess文件使用的配置語法和主配置文件同樣。AllowOverride指令按類別決定了.htaccess文件中哪些指令纔是有效的。若是一個指令容許在.htaccess中使用,那麼在本手冊的說明中,此指令會有一個覆蓋項段,其中說明了爲使此指令生效而必須在AllowOverride指令中設置的值。
(不)使用.htaccess文件的場合
通常狀況下,不該該使用.htaccess文件,除非你對主配置文件沒有訪問權限。有一種很常見的誤解,認爲用戶認證只能經過.htaccess文件實現,其實並非這樣,把用戶認證寫在主配置文件中是徹底可行的,並且是一種很好的方法。
.htaccess文件應該被用在內容提供者須要針對特定目錄改變服務器的配置而又沒有root權限的狀況下。若是服務器管理員不肯意頻繁修改配置,則能夠容許用戶經過.htaccess文件本身修改配置,尤爲是ISP在同一個機器上運行了多個用戶站點,而又但願用戶能夠本身改變配置的狀況下。
雖然如此,通常都應該儘量地避免使用.htaccess文件。任何但願放在.htaccess文件中的配置,均可以放在主配置文件的<Directory>段中,並且更高效。
避免使用.htaccess文件有兩個主要緣由。
首先是性能。若是AllowOverride啓用了.htaccess文件,則Apache須要在每一個目錄中查找.htaccess文件,所以,不管是否真正用到,啓用.htaccess都會致使性能的降低。另外,對每個請求,都須要讀取一次.htaccess文件。
還有,Apache必須在全部上級的目錄中查找.htaccess文件,以使全部有效的指令都起做用(參見指令的生效),因此,若是請求/www/htdocs/example中的頁面,Apache必須查找如下文件:
/.htaccess
/www/.htaccess
/www/htdocs/.htaccess
/www/htdocs/example/.htaccess
總共要訪問4個額外的文件,即便這些文件都不存在。(注意,這可能僅僅因爲容許根目錄"/"使用.htaccess ,雖然這種狀況並很少。)
其次是安全。這樣會容許用戶本身修改服務器的配置,這可能會致使某些意想不到的修改,因此請認真考慮是否應當給予用戶這樣的特權。可是,若是給予用戶較少的特權而不能知足其須要,則會帶來額外的技術支持請求,因此,必須明確地告訴用戶已經給予他們的權限,說明AllowOverride設置的值,並引導他們參閱相應的說明,以避免往後生出許多麻煩。
注意,在/www/htdocs/example目錄下的.htaccess文件中放置指令,與在主配置文件中<Directory /www/htdocs/example>段中放置相同指令,是徹底等效的。
/www/htdocs/example目錄下的.htaccess文件的內容:
AddType text/example .exm
httpd.conf文件中摘錄的內容:
<Directory /www/htdocs/example>
AddType text/example .exm
</Directory>
可是,把配置放在主配置文件中更加高效,由於只須要在Apache啓動時讀取一次,而不是在每次文件被請求時都讀取。
將AllowOverride設置爲none能夠徹底禁止使用.htaccess文件:
AllowOverride None
指令的做用範圍
.htaccess文件中的配置指令做用於.htaccess文件所在的目錄及其全部子目錄,可是很重要的、須要注意的是,其上級目錄也可能會有.htaccess文件,而指令是按查找順序依次生效的,因此一個特定目錄下的.htaccess文件中的指令可能會覆蓋其上級目錄中的.htaccess文件中的指令,即子目錄中的指令會覆蓋父目錄或者主配置文件中的指令。
疑難解答
若是在.htaccess文件中的某些指令不起做用,可能有多種緣由。
最多見的緣由是AllowOverride指令沒有被正確設置,必須確保沒有對此文件區域設置 AllowOverride None 。有一個很好的測試方法,就是在.htaccess文件隨便增長點無心義的垃圾內容,若是服務器沒有返回了一個錯誤消息,那麼幾乎能夠判定設置了 AllowOverride None 。
在訪問文檔時,若是收到服務器的出錯消息,應該檢查Apache的錯誤日誌,能夠知道.htaccess文件中哪些指令是不容許使用的,也可能會發現須要糾正的語法錯誤。
.htaccess工具
不會寫的朋友,在這介紹一款很不錯.htaccess的重定向—URL重寫工具rewriting-tool
--------------------------------------------------------------------------------
htaccess語法教程
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$
RewriteCond %{REQUEST_URI} !^/blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /blog/$1
# 沒有輸入文件名的默認到到首頁
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$
RewriteRule ^(/)?$ blog/index.php [L]
下面我開始解說一下上面的意思:
【RewriteEngine On】
表示重寫引擎開,關閉off,做用就是方便的開啓或關閉如下的語句,這樣就不須要一條一條的註釋語句了。
【RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$】
這是重寫條件,前面%{HTTP_HOST}表示當前訪問的網址,只是指前綴部分,格式是www.xxx.com不包括「http://」和「/」,^表示 字符串開始,$表示字符串結尾,\.表示轉義的. ,若是不轉義也行,推薦轉義,防止有些服務器不支持,?表示前面括號www\.出現0次或1次,這句規則的意思就是若是訪問的網址是xxx.com或者 www.xxx.com就執行如下的語句,不符合就跳過。
【RewriteCond %{REQUEST_URI} !^/blog/】
也是重寫條件,%{REQUEST_URI}表示訪問的相對地址,就是相對根目錄的地址,就是域名/後面的成分,格式上包括最前面的「/」,!表示非,這句語句表示訪問的地址不以/blog/開頭,只是開頭^,沒有結尾$
【RewriteCond %{REQUEST_FILENAME} !-f】
【RewriteCond %{REQUEST_FILENAME} !-d】
這兩句語句的意思是請求的文件或路徑是不存在的,若是文件或路徑存在將返回已經存在的文件或路徑
【RewriteRule ^(.*)$ /blog/$1】
重寫規則,最重要的部分,意思是當上面的RewriteCond條件都知足的時候,將會執行此重寫規則,^(.*)$是一個正則表達的 匹配,匹配的是當前請求的URL,^(.*)$意思是匹配當前URL任意字符,.表示任意單個字符,*表示匹配0次或N次(N>0),後面 /blog/$1是重寫成分,意思是將前面匹配的字符重寫成/blog/$1,這個$1表示反向匹配,引用的是前面第一個圓括號的成分,即^(.*)$中 的.* ,其實這兒將會出現一個問題,後面討論。
【RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$】
【RewriteRule ^(/)?$ blog/index.php [L]】
這兩句的意思是指請求的host地址是www.xxx.com是,若是地址的結尾只有0個或者1個「/」時,將會重寫到子目錄下的主頁,我猜測這主要由於重寫後的地址是不能自動尋找主頁的,須要本身指定。
如今說說出現的問題,RewriteRule ^(.*)$ /blog/$1 前部分 ^(.*)$ 將會匹配當前請求的url。
例如:請求網址是http://www.xxx.com/a.html,究竟是匹配整個http://www.xxx.com/a.html,仍是隻匹配/a.html即反斜槓後面的成分,仍是隻匹配a.html。
答案是:根據RewriteBase規則規定,若是rewritebase 爲/,將會匹配a.html,不帶前面的反斜槓,因此上條語句應該寫成RewriteRule ^(.*)$ blog/$1(不帶/),不過實際應用上帶上前面的反斜槓,也能夠用,可能帶不帶都行。如今問題出來了,若是不設置rewritebase 爲/ ,將會匹配整個網址http://www.xxx.com/a.html,顯然這是錯誤的,因此應該添加這條:RewiteBase /
還有一個問題是,不能保證每一個人輸入的網址都是小寫的,若是輸入大寫的呢,linux系統是區分大小寫的,因此應該在RewriteCond後添加[NC]忽略大小寫的。
至此,完整的語句應該是:
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
# 沒有輸入文件名的默認到到首頁
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ [NC]
RewriteRule ^(/)?$ blog/index.php [L]
若是後面還繼續有語句的,就不該該加上最後的[L],由於這是表示最後一條語句的意思。
防盜鏈的語句,一樣須要添加RewiteBase /,以下:
RewriteEngine on
RewiteBase /
RewriteCond %{HTTP_REFERER} !^$ [NC]
RewriteCond %{HTTP_REFERER} !xxx.info [NC]
RewriteRule \.(jpg|gif|png|bmp|swf|jpeg)$ /error/daolian.gif [R,NC,L]
若是後面還繼續有語句的,就不該該加上最後的[L],/error/daolian.gif爲別人盜鏈時顯示的圖片。
下面附上簡單的語法規則和flags
【RewriteCond語法】
RewriteCond TestString CondPattern [flags]
rewritecond的其餘用法:
"-d"(目錄)
將TestString視爲一個路徑名並測試它是否爲一個存在的目錄。
"-f"(常規文件)
將TestString視爲一個路徑名並測試它是否爲一個存在的常規文件。
"-s"(非空的常規文件)
將TestString視爲一個路徑名並測試它是否爲一個存在的、尺寸大於0的常規文件。
"-l"(符號鏈接)
將TestString視爲一個路徑名並測試它是否爲一個存在的符號鏈接。
"-x"(可執行)
將TestString視爲一個路徑名並測試它是否爲一個存在的、具備可執行權限的文件。該權限由操做系統檢測。
"-F"(對子請求存在的文件)
檢查TestString是否爲一個有效的文件,並且能夠在服務器當前的訪問控制配置下被訪問。它使用一個內部子請求來作檢查,因爲會下降服務器的性能,因此請謹慎使用!
"-U"(對子請求存在的URL)
檢查TestString是否爲一個有效的URL,並且能夠在服務器當前的訪問控制配置下被訪問。它使用一個內部子請求來作檢查,因爲會下降服務器的性能,因此請謹慎使用!
【RewriteRule語法:】
RewriteRule Pattern Substitution [flags]
【flags】
"chain|C"(連接下一規則)
此標記使當前規則與下一個規則相連接。它產生這樣的效果:若是一個規則被匹配,則繼續處理其後繼規則,也就是這個標記不起做用;若是該規則不被匹配,則其後繼規則將被跳過。好比,在一個目錄級規則中執行一個外部重定向時,你可能須要刪除」.www」(此處不該該出現」.www」)。
"cookie|CO=NAME:VAL:domain[:lifetime[:path]]"(設置cookie)
在客戶端設置一個cookie。cookie的名稱是NAME,值是VAL。domain是該cookie的域,好比".apache.org",可選的lifetime是cookie的有效期(分鐘),可選的path是cookie的路徑。
"env|E=VAR:VAL"(設置環境變量)
此標記將環境變量VAR的值爲VAL,VAL能夠包含可擴展的正則表達式反向引用($N和%N)。此標記能夠屢次使用以設置多個變量。這些變量能夠在其後許多狀況下被間接引用,一般是在XSSI(<!–#echo var=」VAR」–>)或CGI($ENV{"VAR"})中,也能夠在後繼的RewriteCond指令的CondPattern參數中經過%{ENV:VAR}引用。使用它能夠記住從URL中剝離的信息。
"forbidden|F"(強制禁止URL)
強制禁止當前URL,也就是當即反饋一個HTTP響應碼403(被禁止的)。使用這個標記,能夠連接若干個RewriteConds來有條件地阻塞某些URL。
"gone|G"(強制廢棄URL)
強制當前URL爲已廢棄,也就是當即反饋一個HTTP響應碼410(已廢棄的)。使用這個標記,能夠標明頁面已經被廢棄而不存在了。
"handler|H=Content-handler"(強制指定內容處理器)
強自制定目標文件的內容處理器爲Content-handler。例如,用來模擬mod_alias模塊的ScriptAlias指令,以強制映射文件夾內的全部文件都由」cgi-script」處理器處理。
"last|L"(結尾規則)
當即中止重寫操做,並再也不應用其餘重寫規則。它對應於Perl中的last命令或C語言中的break命令。這個標記用於阻止當前已被重寫的URL被後繼規則再次重寫。例如,使用它能夠重寫根路徑的URL("/")爲實際存在的URL(好比:"/e/www/")。
"next|N"(從頭再來)
從新執行重寫操做(從第一個規則從新開始)。此時再次進行處理的URL已經不是原始的URL了,而是經最後一個重寫規則處理過的URL。它對應於Perl中的next命令或C語言中的continue命令。此標記能夠從新開始重寫操做(當即回到循環的開頭)。可是要當心,不要製造死循環!
"nocase|NC"(忽略大小寫)
它使Pattern忽略大小寫,也就是在Pattern與當前URL匹配時,"A-Z"和"a-z"沒有區別。
"noescape|NE"(在輸出中不對URI進行轉義)
此標記阻止mod_rewrite對重寫結果應用常規的URI轉義規則。 通常狀況下,特殊字符("%", "$", ";"等)會被轉義爲等值的十六進制編碼("%25′, "%24′, "%3B"等)。此標記能夠阻止這樣的轉義,以容許百分號等符號出如今輸出中,好比:
RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]
可使"/foo/zed轉向到一個安全的請求"/bar?arg=P1=zed"。
"nosubreq|NS"(不對內部子請求進行處理)
在當前請求是一個內部子請求時,此標記強制重寫引擎跳過該重寫規則。好比,在mod_include試圖搜索目錄默認文件(index.xxx)時,Apache會在內部產生子請求。對於子請求,重寫規則不必定有用,並且若是整個規則集都起做用,它甚至可能會引起錯誤。因此,能夠用這個標記來排除某些規則。
使用原則:若是你爲URL添加了CGI腳本前綴,以強制它們由CGI腳本處理,但對子請求處理的出錯率(或者資源開銷)很高,在這種狀況下,可使用這個標記。
"proxy|P"(強制爲代理)
此標記使替換成分被內部地強制做爲代理請求發送,並當即中斷重寫處理,而後把處理移交給mod_proxy模塊。你必須確保此替換串是一個可以被mod_proxy處理的有效URI(好比以http://hostname開頭),不然將獲得一個代理模塊返回的錯誤。使用這個標記,能夠把某些遠程成分映射到本地服務器域名空間,從而加強了ProxyPass指令的功能。
注意:要使用這個功能,必須已經啓用了mod_proxy模塊。
"passthrough|PT"(移交給下一個處理器)
此標記強制重寫引擎將內部request_rec結構中的uri字段設置爲filename字段的值,這個小小的修改使得RewriteRule指令的輸出可以被(從URI轉換到文件名的)Alias, ScriptAlias, Redirect等指令進行後續處理[原文:This flag is just a hack to enable post-processing of the output of RewriteRule directives, using Alias, ScriptAlias, Redirect, and other directives from various URI-to-filename translators.]。舉一個能說明其含義的例子: 若是要將/abc重寫爲/def, 而後再使用mod_alias將/def轉換爲/ghi,能夠這樣:
RewriteRule ^/abc(.*) /def$1 [PT]
Alias /def /ghi
若是省略了PT標記,雖然將uri=/abc/…重寫爲filename=/def/…的部分運做正常,可是後續的mod_alias在試圖將URI轉換到文件名時會遭遇失效。
注意:若是須要混合使用多個將URI轉換到文件名的模塊時,就必須使用這個標記。。此處混合使用mod_alias和mod_rewrite就是個典型的例子。
"qsappend|QSA"(追加查詢字符串)
此標記強制重寫引擎在已有的替換字符串中追加一個查詢字符串,而不是簡單的替換。若是須要經過重寫規則在請求串中增長信息,就可使用這個標記。
"redirect|R [=code]"(強制重定向)
若Substitution以http://thishost[:thisport]/(使新的URL成爲一個URI)開頭,能夠強制性執行一個外部重定向。若是沒有指定code,則產生一個HTTP響應碼302(臨時性移動)。若是須要使用在300-400範圍內的其餘響應代碼,只需在此指定便可(或使用下列符號名稱之一:temp(默認), permanent, seeother)。使用它能夠把規範化的URL反饋給客戶端,如將」/~」重寫爲」/u/」,或始終對/u/user加上斜槓,等等。
注意:在使用這個標記時,必須確保該替換字段是一個有效的URL。不然,它會指向一個無效的位置!而且要記住,此標記自己只是對URL加上http://thishost[:thisport]/前綴,重寫操做仍然會繼續進行。一般,你還會但願中止重寫操做而當即重定向,那麼就還須要使用"L'標記。
"skip|S=num"(跳事後繼規則)
此標記強制重寫引擎跳過當前匹配規則以後的num個規則。它能夠模擬if-then-else結構:最後一個規則是then從句,而被跳過的skip=N個規則是else從句。注意:它和"chain|C"標記是不一樣的!
"type|T=MIME-type"(強制MIME類型)
強制目標文件的MIME類型爲MIME-type,能夠用來基於某些特定條件強制設置內容類型。好比,下面的指令可讓.php文件在以.phps擴展名調用的狀況下由mod_php按照PHP源代碼的MIME類型(application/x-httpd-php-source)顯示:
RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]html