我正在嘗試將對我網站的所有請求傳遞到我的 webroot 中的子檔案夾。
這是我的檔案夾結構:
/webroot
current
releases
release1
index.html
en
index.html
release2
index.html
en
index.html
...
.htaccess
該current檔案夾是一個符號鏈接,指向檔案夾中的一個檔案releases夾。這個想法是,當我發布新版本時,會在檔案夾中創建一個新檔案releases夾,current然后符號鏈接指向這個新檔案夾。
然后,在我的 .htaccess 中,我嘗試將所有請求傳遞給current符號鏈接。因此,例如,如果用戶請求,/en則應通過符號鏈接路由請求,而瀏覽器 URL 看起來像https://example.com/en實際請求最終會在https://example.com/current/en
現在,只要請求以斜杠結尾,這就可以完美地作業,例如,https://example.com/en/但是如果我洗掉了斜杠,路由就可以作業,但是瀏覽器中的 URL 將是https://example.com/current/en
這是我在 .htaccess 中所做的重寫:
Options FollowSymlinks -MultiViews -Indexes
DirectorySlash On
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !^/current/
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ current/$1 [L]
這是日志檔案
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'en'
[perdir /path/to/webroot/] RewriteCond: input='/en' pattern='!^/current/' => matched
[perdir /path/to/webroot/] RewriteCond: input='' pattern='^$' => matched
[perdir /path/to/webroot/] rewrite 'en' -> 'current/en'
[perdir /path/to/webroot/] add per-dir prefix: current/en -> /path/to/webroot/current/en
[perdir /path/to/webroot/] trying to replace prefix /path/to/webroot/ with /
strip matching prefix: /path/to/webroot/current/en -> current/en
add subst prefix: current/en -> /current/en
[perdir /path/to/webroot/] internal redirect with /current/en [INTERNAL REDIRECT]
[perdir /path/to/webroot/] strip per-dir prefix: /path/to/webroot/current/en -> current/en
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'current/en'
[perdir /path/to/webroot/] RewriteCond: input='/current/en' pattern='!^/current/' => not-matched
[perdir /path/to/webroot/] pass through /path/to/webroot/current/en
[perdir /path/to/webroot/] strip per-dir prefix: /path/to/webroot/current/en/ -> current/en/
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'current/en/'
[perdir /path/to/webroot/] RewriteCond: input='/current/en/' pattern='!^/current/' => not-matched
[perdir /path/to/webroot/] pass through /path/to/webroot/current/en/
[perdir /path/to/webroot/] strip per-dir prefix: /path/to/webroot/current/en/index.php -> current/en/index.php
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'current/en/index.php'
[perdir /path/to/webroot/] RewriteCond: input='/current/en/index.php' pattern='!^/current/' => not-matched
[perdir /path/to/webroot/] pass through /path/to/webroot/current/en/index.php
[perdir /path/to/webroot/] strip per-dir prefix: /path/to/webroot/current/en/index.html -> current/en/index.html
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'current/en/index.html'
[perdir /path/to/webroot/] RewriteCond: input='/current/en/index.html' pattern='!^/current/' => not-matched
[perdir /path/to/webroot/] pass through /path/to/webroot/current/en/index.html
uj5u.com熱心網友回復:
但是如果我洗掉尾部斜杠路由作業但瀏覽器中的 URL 將是
https://example.com/current/en
我假設您的意思是https://example.com/current/en/(帶有斜杠)。
發生這種情況是因為 mod_dir 試圖通過在省略時將尾部斜杠附加到物理目錄來“修復”(使用 301 重定向)URL(這是目錄索引正常作業所必需的)。此“修復”發生在 URL 被重寫到子目錄之后(因為 URL 路徑/en最初并未映射到子目錄)。
您可以禁用 mod_dir 的這種行為,以便不附加斜杠;但這會變得混亂(然后您需要根據需要手動附加斜杠)并且可能會引發安全問題。
相反,您需要確保始終使用尾部斜杠鏈接到 URL,并在mod_dir 這樣做.htaccess 之前手動更正任何省略尾部斜杠的 URL 。
您現有的重寫到/current子目錄的重寫看起來沒問題,盡管您不一定需要檢查請求是否已經用于/current/(第一個條件)。(通過檢查請求是否已經開始/current/,那么您允許直接請求到實際的符號鏈接檔案系統位置 - 盡管這可能是一個要求?)
因此,在您現有的重寫之前,添加以下重定向:
# Fix any requests for directories that omit the trailing slash
RewriteCond %{DOCUMENT_ROOT}/current/$1 -d
RewriteRule ^(. [^/])$ /$1/ [R=301,L]
給定一個請求/example,上面首先檢查是否/current/example作為目錄存在(盡管是一個符號鏈接的目錄)。如果是,那么它會發出 301 重定向以將尾部斜杠附加到原始 URL,而不是重寫的 URL。例如。/example被重定向到/example/,然后將其重寫為/current/example/。
首先使用 302(臨時)重定向進行測驗,以避免潛在的快取問題。
您需要清除瀏覽器快取,因為 mod_dir 的錯誤 301(永久)重定向將被瀏覽器快取。
更新:
應該無法直接訪問“當前”檔案夾中的任何檔案或檔案夾。目前,這是可能的...
正如上面所暗示的,您可以簡單地洗掉檢查是否尚未以 . 開頭的第一個條件。因此,所有直接請求都無條件地重寫為. 因此,請求將被重寫為,從而導致 404。REQUEST_URI/current//current//current/en//current/current/en
但是,用戶仍然可以直接請求檔案系統位置,完全繞過符號鏈接。例如。/releases/release1/en/.
要阻止這兩個位置的直接訪問,您可以添加以下作為第一條規則:
# Block direct access to "/current/" and "/releases/"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(current|releases)($|/) - [F]
請求/current/...或/releases/...直接會導致“403 Forbidden”。或者將其更改F為R=404提供“404 Not Found”(盡管使用了標志,但不會發生重定向)。R
檢查REDIRECT_STATUS環境變數(如您的原始規則)確保請求仍然可以在內部重寫到這些位置。(REDIRECT_STATUS在客戶端的初始請求中,env var 為空,但在第一次重寫后設定為 HTTP 回應狀態(例如“200”)。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/505682.html
