[PHP] htaccess 探祕

.htaccess訪問控制(Allow/Deny)

1. 驗證是否支持.htaccess

在目錄下新建一個.htaccess 文件,隨筆輸入一串字符(毫無心義),看看什麼反應,若是是500錯誤,說明目前環境是支持 .htaccessphp

fjdklsaj

轉載請註明: http://www.cnblogs.com/ganiks/ css

2. deny from all

# no one gets in here!
deny from all

3. Order命令

Order命令是一個難點,也是配置apache的基礎,它決定了Apache處理訪問規則的順序。 html

經過Allow,Deny參數,Apache首先找到並應用Allow命令,而後應用Deny命令,以阻止全部訪問。
經過Deny,Allow參數,Apache首先找到並應用Deny命令,而後應用Allow命令,以容許全部訪問。 正則表達式

假設本地的IP爲 192.168.4.126apache

Order Deny,Allow
Deny from All
Allow from 192.168.4.126

本地訪問成功,非本地IP訪問 403 Forbidden 數組

4. 利用.htaccess過濾域名或網絡主機(Allow/Deny)

下例能夠限制全部含有「domain.com」的網絡主機訪問網站:瀏覽器

Order Allow,Deny
Allow from all
Deny from .*domain\.com.*

5. 禁止訪問指定文件

Order Deny,Allow
Deny from All
Allow from 192.168.4.126 

<Files favicon.ico>
	order allow,deny
	deny from all
</Files>

6. 禁止訪問指定類型的文件

Order Deny,Allow
Deny from All
Allow from 192.168.4.126 

<FilesMatch ".(txt|ico)$">
	order allow,deny
	deny from all
</FilesMatch>

Files以後的波浪線用於開啓「正則表達式」分析。請注意,這是個過期的用法,Apache更推薦使用指令[3]
正則表達式必須在雙引號之間,有關htaccess的正則表達式用法,請查閱本站《.htaccess正則表達式》一文。
雙引號中的「管道符」(|)用於將兩種文件類型(.log和.exe)分開,至關於邏輯「或」
Order命令必須嵌在Files節(Section)中,不然將會應用到全部文件
Satisfy All表示必須同時知足主機級別(Allow/Denay)和用戶級別(Require)的限制,All是默認值,該行能夠省略。安全

利用.htaccess進行密碼保護與驗證

暫不研究 服務器

目錄瀏覽與主頁

1. 啓用和禁用目錄瀏覽

Options All -Indexes
IndexIgnore *
Options All +Indexes

這3種設置分別對應下面3個圖:網絡



2. 禁用瀏覽某些文件

IndexIgnore *.php *.txt~ Copy*

3. 自定義目錄瀏覽頁面的style

<IfModule mod_autoindex.c>
 IndexOptions FancyIndexing 
</ifModule>

http://corz.org/public/images/demo/
http://corz.org/server/resources/file_view.htaccess.txt?raw=true

4. 配置目錄主頁文件

DirectoryIndex index.html index.php index.htm

5. 配置錯誤頁面

# custom error documents
ErrorDocument 401 /err/401.php
ErrorDocument 403 /err/403.php
ErrorDocument 404 /err/404.php
ErrorDocument 500 /err/500.php

URL重寫與URL重定向

1、準備開始:mod_rewrite
2、利用.htaccess實現URL重寫(rewrite)與URL重定向(redirect)
將.htm頁面映射到.php
臨時重定向(R=302)與永久重定向(R=301)
爲何要用重定向?——重定向和URL重寫的區別
長短地址轉換
去掉www
加上www
支持多域名訪問
3、改寫查詢字符串QUERY_STRING
利用QSA轉換查詢字符串QUERY_STRING
利用RewriteCond改寫查詢字符串QUERY_STRING
QSA與RewriteCond雙劍齊發
剝離查詢字符串
4、利用RewriteCond和RewriteRule進行訪問控制
文件訪問控制
用.htaccess阻止User-agent
用.htaccess阻止盜鏈(hot-linking)
References

1. 準備開始: mod_rewrite

sudo a2enmod rewrite
<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine on
    # More rules below
    ...
</IfModule>
  • FollowSymlinks必須啓用,這是 rewrite 引擎的安全需求
  • mod_rewrite 會處理全部的提交給Apache 的URL請求, 並與以後的規則進行匹配

2. 利用 .htaccess 實現URL重寫和URL重定向

2.1 將.htm頁面映射到.php頁面
<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine on
    RewriteRule ^(.*)\.htm$ $1.php [NC]
</IfModule>

[NC] No Case(不區分大小寫): 對客戶端請求的URL不區分大小寫
若是經過.htm進入,瀏覽器地址欄顯示的是.htm擴展名,但服務器上實際執行的是.php
必須保證服務器上有對應的.php,不然會404
瀏覽器和搜索引擎能夠同時經過.htm和.php訪問網頁

test.htm
this is .htm
test.php
this is .php

2.2 臨時重定向(R=302)與永久重定向(R=301)
<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteBase /
    RewriteRule ^(.*)\.htm$ $1.php [R,NC,L]
</IfModule>

注意事項:

  • 該RewriteRule可以將.htm靜態頁面重定向到.php動態頁面
  • 若是經過.htm進入,瀏覽器地址欄會自動轉爲.php,這也是重定向的本質
  • 必須保證服務器上有對應的.php,不然會404
  • 瀏覽器和搜索引擎能夠同時經過.htm和.php訪問網頁
  • 若是該目錄上存在.htm,將被忽略
  • RewriteBase定義了重寫基準目錄。

    • 例如,若是你將虛擬站點設置在/var/www目錄下,刪除這行將會致使重定向到http://yourdomain.com/var/www/1.php。顯然這是找不到的,並且你也不會但願用戶看見你的服務器的目錄結構。
  • 再舉個例子,若是RewriteBase /base/,那麼將會重定向到http://yourdomain.com/base/1.php。
  • 對於重寫基準目錄,咱們還能夠經過將$1.php變成/$1.php實現直接變換,這時就能夠將RewriteBase省略。
  • 字母R表示臨時重定向,至關於[R=302,NC]。關於重定向代碼,請參考本站《HTTP協議重定向編碼》
  • 字母L表示若是能匹配本條規則,那麼本條規則是最後一條(Last),忽略以後的規則。

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteBase /
    RewriteRule ^(.*)$ http://newdomain/$1 [R=301,NC,L]
</IfModule>
  • 這個規則告訴瀏覽器和搜索引擎,網站地址發生了永久性變動,用戶的URL請求將會被髮送給新的域名(主機)處理。
  • 因爲是重定向到新的主機地址,RewriteBase也就沒有出現的必要了。
2.3 爲何要重定向——重定向和URL重寫的區別
  • 經過重定向,瀏覽器知道頁面位置發生變化,從而改變地址欄顯示的地址
  • 經過重定向,搜索引擎意識到頁面被移動了,從而更新搜索引擎索引,將原來失效的連接從搜索結果中移除
  • 臨時重定向(R=302)和永久重定向(R=301)都是親搜索引擎的,是SEO的重要技術
  • URL重寫用於將頁面映射到本站另外一頁面,若重寫到另外一網絡主機(域名),則按重定向處理
2.4 長短地址轉換

利用URL重寫,咱們能夠很方便地實現長短地址的轉換,可是用重定向就不合適了。

RewriteEngine On
RewriteRule ^grab /public/files/download/download.php

若訪問

http://mysite/grab?file=my.zip

則會執行該頁面:

http://mysite/public/files/download/download.php?file=my.zip
2.5 去掉 www
<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
    RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]
</IFModule>
2.6 加上 www
<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^(.*)$
    RewriteRule (.*) http://www\.%1/$1 [R=301,L]
</IFModule>
2.7 支持多域名訪問

若是你不湊巧買到了不支持多域名的主機,那麼.htaccess或許能夠幫助你。如今假設你有域名domain-one.com和domain- two.com,而且在服務器根目錄有對應文件夾one和two,那麼經過下面的改寫就能讓Apache同時接受者兩個域名的請求:

#two domains served from one root..
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]

3. 改寫查詢字符串 QUERY_STRING

查詢字符串是指URL請求中「問號」後面的部分。好比,http://mysite/grab?foo=bar 中粗體部分就是查詢字符串,其中變量名是foo,值是bar。

3.1 利用 QSA 轉換查詢字符串 QUERY_STRING

QSA(Query String Appending) 用於在 URI中截取查詢字符串, 這個截取操做室經過小括號正則實現的

RewriteEngine On
RewriteRule /pages/(.+) /page.php?page=$1 [QSA]
RewriteRule ^/([^/]+)/([^/]+)/? /index.php?first-var=$1&second-var=$2 [QSA]

這裏經過 QSA , 將簡單的連接 /simple/flat/link/映射到 server-side.php?first-val=flat&second-var=link

  • 將會把請求 /pages/123?one=two 映射到 /page.php?page=123&one=two
  • 若是沒有 QSA標誌,將會映射到 /page.php?page=123
  • 若是沒有用到小括號正則,就不須要QSA,像《長短地址轉換》中同樣
  • 小括號正則表達式能夠截取查詢字符串中的內容,可是若是沒有開啓QSA標誌,那麼 /page.php?page=$1中 問號以後的部分將會剝離丟棄。
3.2 利用RewriteCond改寫查詢字符串QUERY_STRING
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.*)
RewriteRule ^grab(.*) /page.php?bar=%1
  • 該規則將訪問請求http://mysite/grab?foo=bar 轉換爲 http://mysite/page.php?bar=bar
  • RewriteCond用於捕獲查詢字符串(QUERY_STRING)中變量foo的值,並存儲在%1中
  • QUERY_STRING是Apache定義的「變量=值」向量(數組)
3.3 QSA與RewriteCond雙劍齊發
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.+)
RewriteRule ^grab/(.*) /%1/index.php?file=$1 [QSA]
  • 會把 /grab/foobar.zip?level=5&foo=bar 映射到 /bar/index.php?file=foobar.zip&level=5&foo=bar
  • 轉換後根目錄是bar目錄
  • foobar.zip?level=5中的「問號」變成了foobar.zip&level=5中的「與」符號
3.4 剝離查詢字符串

只需在要開始剝離的連接後面加個「問號」,而且不要啓用QSA標誌,就可剝離查詢字符串

RewriteEngine On
# Whatever QS is
RewriteCond %{QUERY_STRING} . 
# I don't want it with Question mark
RewriteRule foo.php(.*) /foo.php? [L]

4. 利用 RewriteCondRewriteRule進行訪問控制

咱們在第一篇.htaccess基礎中提到了不少有用的訪問控制方法,其實經過Rewrite也能實現相似的功能,並且能夠更強大!

4.1 文件訪問控制

以前利用Order、Files及FilesMatch命令實現的訪問控制能夠知足大部分要求,可是當用戶被拒絕時,他們看到的是碩大的「403 Forbidden」,若是你不想傷害用戶的感情,就須要顯示一些別的東西,經過Rewrite就能夠實現這個特性:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !^(.+)\.css$
RewriteCond %{REQUEST_FILENAME} !^(.+)\.js$
RewriteCond %{REQUEST_FILENAME} !special.zip$
RewriteRule ^(.+)$ /chat/ [NC]

該規則將僅容許用戶請求.css, .js類型的文件,還有special.zip文件
RewriteRule 後面指定了限制規則:映射到/char/目錄下處理
RewriteCond 後面的「感嘆號」(!)起到了「否認」做用,它代表,對不知足後面正則表達式者應用RewriteRule規則,也就是對當前類型的文件將不該用規則
RewriteCond 之間是以邏輯「與」鏈接的,也就是隻有當三個條件都不知足時才執行RewriteRule
該規則也會限制訪問.htm, .jpg等格式
該規則不能夠放在虛擬站點根目錄(/)下,不然會死循環
若是是二級目錄,如/test/,那麼傳入RewriteCond的參數是以/test/開始的,所以從(.+)得到的文件名也含有/test/,讀者必須對此多加當心
要想僅得到文件名,能夠將(.+)替換成([^/]+),而且去掉符號^,以下所示:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !([^/]+)\.css$
RewriteCond %{REQUEST_FILENAME} !([^/]+)\.js$
RewriteRule ^(.+)$ /chat/ [NC]
4.2 用.htaccess阻止User-agent

什麼是User-agent?User-agent用於瀏覽器向服務器「自報家門」,更確切的說是全部HTTP客戶端都得用User-agent向 服務器「自報家門」,以便服務器對不一樣的客戶端做出不一樣響應。好比,某站點可能須要對瀏覽器、搜索引擎crawl還有各種下載工具做出不一樣的響應。服務器 就是經過所謂的User-agent進行區分的。
若是你的服務器提供某些資源的下載,那麼你就必須多加當心諸如「迅雷」等下載軟件,由於它們可能把你網站資源吸乾,而且影響你的正常訪客訪問。爲此,咱們能夠利用Rewrite限制某些UA的訪問:

RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} 2.0.50727 [NC]
RewriteRule . abuse.txt [L]

該規則限制「迅雷」客戶端下載資源,並將下載文件重置到abuse.txt
HTTP_USER_AGENT是Apache的內置變量
2.0.50727是迅雷User-agent的特徵字符串
RewriteRule後面的「點」表示「任意URI」,也就是無論請求的是什麼,都輸出abuse.txt
一般,咱們不會僅限制一個UA。利用[OR]便可實現對多個UA做出統一處理:

RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} 2.0.50727 [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [NC,OR]
# etc..
RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [NC]
RewriteRule . abuse.txt [L]
4.3 用.htaccess阻止盜鏈(hot-linking)

盜鏈,特別是圖片,是很是可恥的!哪怕將圖片複製到本身服務器上,也比盜用他人的圖片連接來得光彩!(吐糟完畢)
.htaccess的Rewrite功能能夠提供很是簡單、有效的方法阻止這種可恥行爲:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?lesca\.me/ [NC]
RewriteCond %{REQUEST_URI} !hotlink\.png [NC]
RewriteRule .*\.(gif|jpg|png)$ /hotlink.png [NC]

簡單解釋一下該規則的功能:

  • 除本站之外其餘網站都不得引用本站圖片,具體能夠理解爲
  • 若是引用站點爲「空」或者是「本站」,或者,所引用對象是「hotlink.png」,那麼就容許訪問
  • 再次提醒,RewriteCond之間默認的邏輯鏈接詞是邏輯「與」
  • 這裏的難點是理解邏輯轉換,即德·摩根定律

轉載請註明: http://www.cnblogs.com/ganiks/

htaccess正則表達式

#
位於行首時表示註釋。
[F]
Forbidden(禁止): 命令服務器返回 403 Forbidden錯誤給用戶瀏覽器
[L]
Last rule(最後一條規則): 告訴服務器在本條規則執行完後中止重寫URL
[N]
Next(下一條規則): 告訴服務器繼續重寫,指導全部重寫指令都執行過
[G]
Gone(丟失): 命令服務器返回410 GONE(no longer exists)錯誤消息
[P]
Proxy(代理): 告訴服務器經過mod_proxy模塊處理用戶請求
[C]
Chain(捆綁): 告訴服務器將當前的規則和前面的規則進行捆綁
[R]
Redirect(重定向): 命令服務器發出重定向消息,以便用戶瀏覽器發出rewritten/modified(重寫/修改)URL的請求
[NC]
No Case(不區分大小寫): 對客戶端請求的URL不區分大小寫
[PT]
Pass Through(放行): 讓mod_rewrite模塊將重寫的URL傳回給Apache作進一步處理
[OR]
Or(邏輯或): 用邏輯「或」將兩個表達式鏈接在一塊兒,若是結果爲「真」,則會應用後繼的相關規則
[NE]
No Escape(禁用轉義): 命令服務器在輸出時禁用轉義字符
[NS]
No Subrequest(禁用子請求): 若是存在內部子請求,則跳過當前命令
[QSA]
Append Query String(追加查詢字符串): 命令服務器在URL末尾追加查詢字符串
[S=x]
Skip(跳過): 若是知足某指定的條件,則跳事後面第x調規則
[E=variable:value]
Environmental Variable(環境變量): 命令服務器將值value賦給變量variable
[T=MIME-type]
Mime Type(MIME類型): 聲明目標資源所屬的MIME類型
[]
匹配一個字符集合,例如[xyz]能夠匹配x, y或者z
[]+
例如[xyz]+會以任何順序、次數匹配x,y,z的出現
[^]
字符^表示字符集的補集。[^xyz]將匹配沒有x,y或者z的字符串
[a-z]
連字符(-)表示匹配從字母a到字母z的全部字符串
a{n}
指定字母a出現的次數爲n次,知足該條件時匹配。例如x{3}僅與xxx匹配
a{n,}
指定字母a出現的次數至少爲n次,例如x{3,}能夠與xxx或者xxxx等匹配
a{n,m}
指定a出現的次數至少爲n到m次。
()
用於將正則表達式分組,知足第一組正則表達式的字符串會被存儲在變量$1中,以此類推。若是括號中的不是正則表達式,例如(perishable)?press 將可以匹配有或者沒有perishable前綴的press
^
位於行首。注意:和中括號中的[^]意義不一樣。
$
位於行末
?
例如 monzas? 會匹配 monza 或者 monzas,而 mon(za)? 會匹配 mon 或者 monza。又如 x? 會匹配「空字符」 或者 一個x
!
邏輯非。例如「!string」 將會匹配除了「string」之外的全部字符串
.
表示任意字符串
-
命令Apache「不要」重寫URL,例如「xxx.domain.com.* – [F]」
+
匹配至少一個任意字符,例如G+匹配以G開頭、而且後面至少有一個字符的字符串
*
匹配零個或多個字符,例如「.*」匹配任意字符串
|
邏輯「或」,與[OR]不一樣的是,它只匹配字符串,例如(x|y)匹配x或者y
\
轉義字符。能夠轉義左括號( 尖字符^ 美圓符號$ 感嘆號! 點. 星號* 管道符號| 右括號) 等
\.
轉義爲點字符(點字符在正則表達式中能夠匹配任意字符)
/*
零個或多個正斜槓
.*
零個或多個任意字符(即,匹配任意字符串,包括空字符)
^$
匹配「空字符」、「空行」
^.*$
匹配任意字符串(僅限一行)
[^/.]
匹配既非「正斜槓」也不是「點」的任意字符
[^/.]+
匹配第一個字符既非「正斜槓」也不是「點」,後繼字符能夠是「正斜槓」或者「點」的字符串
http://
匹配「http://」
^domain.*
匹配以「domain」開始的字符串
^domain\.com$
僅匹配「domain.com」
-d
測試字符串是不是已存在的目錄
-f
測試字符串是不是已存在的文件
-s
測試字符串所指文件是否有「非零」值
HTTP協議重定向編碼

301 – Moved Permanently
302 – Moved Temporarily
403 – Forbidden
404 – Not Found
410 – Gone
相關文章
相關標籤/搜索