2012-06-17 60 views
12

我已經在Google和StackOverflow上找到了解決此問題的答案,但事實是我對.htaccess瞭解不多,並不能幫助我確定正確的答案因爲我的情況是,所以我在這裏問。.htaccess RewriteCond其中URI不包含域

我的情況是,我有幾個站點使用相同的物理目錄作爲它們在服務器上的根目錄。

這一切都工作正常,但我想確保每個網站不能訪問其他圖像等從瀏覽器,除非他們在正確的域名。

目前,我有一個文件的結構是這樣的:

/resources/{resource}/{full_domain_name} 

因此,例如www.domain.co.uk就會有這樣的結構:

http://www.domain.co.uk/resources/images/www.domain.co.uk/some_image.jpg 

但如果www.domain_2.co.uk存在使用相同的物理目錄網站然後他們可以從他們自己的域中查看其他域的資源,如下所示:

http://www.domain_2.co.uk/resources/images/www.domain.co.uk/some_image.jpg 

這不是一個真正的主要問題,因爲這些目錄中絕對沒有敏感信息,但這更令人煩惱,我寧願用戶也無法做到這一點(不是任何人到目前爲止)。

我試圖把.htaccess文件到/資源目錄,但我堅持用正則表達式等

我基本上要確保URI包含當前域名,否則重定向到一個403錯誤頁面。

這是我想出了:

RewriteCond %{REQUEST_URI} !^(/resources/[^/]*/%{HTTP_HOST})(.*)$ 
RewriteRule ^(.*)$ /error/403.php 

我放在[^/]位是因爲有幾個文件夾,例如其原因是:

/resources/images/{full_domain_name} 
/resources/scripts/{full_domain_name} 
/resources/stylesheets/{full_domain_name} 

有誰能幫我做這些條件?

任何幫助,將不勝感激。

+0

你目前的規則是什麼結果?它看起來像它會工作,除了你不需要任何'()'在'/ resources/[^ /] * /%{HTTP_HOST}周圍。'' –

+0

@Michael目前如果我在www.domain.co .uk並轉到www.domain.co.uk/resources/stylesheets/www.domain.co.uk/style.css,例如它總是將我重定向到/error/403.php文件。當我刪除.htaccess規則時,它會找到該文件,因爲它應該正常進行。 –

+0

您實際上並不需要在正則表達式中表示的整個'%{REQUEST_URI}'。您可以匹配http_host'RewriteCond%{REQUEST_URI}!^。+%{HTTP_HOST}' –

回答

10

這是一個了不起的問題,如果我可以,我會有超過10次以上。即使你在這裏有一個可接受的答案,我也會發布我的答案,因爲我真的必須挖掘我所有的Apache資源才能得出答案。這裏是你需要爲這個問題的規則:

Options +FollowSymLinks -MultiViews 
# Turn mod_rewrite on 
RewriteEngine On 
RewriteBase/

RewriteCond %{HTTP_HOST}:%{REQUEST_URI} !^([^:]+):/resources/[^/]+/\1/.+ [NC] 
RewriteRule ^resources/[^/]+/[^/]+/.+ - [F,NC,NE] 

PS:既然我們不能在RHS使用%變量作爲反向參考,我使用正則表達式的特殊反向參考變量\1在這裏RewriteCond

+1

我通常不這樣做,但在這種情況下,我想我會改變我接受的答案,因爲這提供了一個完美的解決方案。感謝您發佈您的答案anubhava,非常感謝! –

+0

非常歡迎您,並感謝您發佈這樣一個有趣的問題,使我學習新的mod_rewrite技巧以及:)。 – anubhava

3

這個條件是不夠的:

RewriteCond %{REQUEUST_URI} !^(/resources/[^/]*/%{HTTP_HOST})(.*)$ 

因爲如果我要求什麼,不/resources/開始,我會得到403.php錯誤頁面。你真正想要的是這樣的:

RewriteCond %{REQUEST_URI} ^/resources/[^/]+/([^/]+)/ 
RewriteCond %{HTTP_HOST} !%1 

或者

RewriteCond %{REQUEST_URI} ^/resources/[^/]+/([^/]+)/ 
RewriteCond %{REQUEST_URI} !^/resources/[^/]+/%{HTTP_HOST}/ 

當第一個條件是檢查該請求的資源,那麼第二個檢查主機。 但是,這些都不會工作,因爲mod_rewrite的RewriteCond指令不允許變量或條件右側的反向引用,只有左側。同樣的,你不能做到這一點無論:

RewriteCond %{REQUEST_URI} ^/resources/[^/]+/([^/]+)/ 
RewriteRule !^/resources/[^/]+/%{HTTP_HOST}/ /error/403.php 

由於重寫規則的表達式不能有變量的原因,因爲它是一個正則表達式,而它確實需要一個%{HTTP_HOST},而不是用在請求中給出的主機替換它。因此總而言之,不,你不能這樣用mod_rewrite的條件來做到這一點。

如果您有權訪問服務器配置或vhost配置,則可嘗試創建RewriteMap並通過%{REQUEST_URI}%{HTTP_HOST}。所以,如果您的地圖被稱爲check_host那麼你的規則可能是這個樣子:

RewriteRule ^resources/[^/]+/([^/]+)/ ${check_host:%{HTTP_HOST}_%{REQUEST_URI}} 

而且你的腳本將只需要解析輸入,它從第一_拆分,解析請求URI,確保主機與HTTP_HOST相同。如果相同,則輸出相同的請求URI,否則輸出錯誤URI。如果您無法訪問服務器或vhost配置,我認爲您運氣不佳。 RewriteMap不能在htaccess文件中定義。

+0

謝謝你的回答Jon Lin。我不知道你無法將%變量或反向引用放入RewriteCond的右側。我選擇嘗試RewriteMap,但如果因爲任何原因我不能這樣做,那麼我相信我會找到mod_rewrite以外的另一種方式:) –