網址:example.com
Joomla 子目錄:example.com/joomla
我希望 example.com/joomla 安裝的 Joomla 是(或看起來是)網站的根目錄,即造訪 example.com 的人會被重定向到 example.com/joompla/index.php,但仍會在 URL 欄中看到 example.com。我還想利用這個機會強制所有傳入連線使用 HTTPS。我已經能夠使用我在網上找到的腳本來完成其中之一,但兩者都不能保持一致性。
這是我到目前為止對 .htaccess 的了解:
RewriteEngine on
RewriteBase /
# Rewrites all URLS without joomla in them
RewriteCond %{REQUEST_URI} !^/joomla/
# Rewrites all URLS with example in them
RewriteCond %{HTTP_HOST} ^(www\.)?example\.
# Rewrite all those to insert /joomla
RewriteRule ^(.*)$ /joomla/$1 [L]
# This works SOME of the time to redirect to https
Header always set Content-Security-Policy "upgrade-insecure-requests;"
# If a request tries to access /joomla directly, redirect it to its secured canonical version
RewriteCond %{THE_REQUEST} joomla/
RewriteRule ^joomla/(.*) http://example.com/$1 [R=301,L]
這似乎在 Chrome 中有時有效,重定向到 Joomla 安裝並切換到 https,但有時我需要重複強制硬重新加載才能到達那裡。它在 Firefox 中永遠無法工作,在加載網站的極少數情況下仍停留在 http 上。
我對 .htaccess 非常陌生,我不確定我是否已經為上述問題開發了最優雅或最全面的解決方案。我在網路上看到了使用各種命令RewriteCond %{HTTPS} !=on
或RewriteCond %{SERVER_PORT} 80
與各種命令一起使用的其他範例RewriteRule
,但我不確定如何將這些命令與現有的 URL 重寫條件結合起來,因此我確信我錯過了邊緣場景。
有更多經驗的人可以指導我完成這件事嗎?這將不勝感激。這幾天我一直在嘗試在網路上找到的腳本的變體,但還沒有找到神奇的字眼。
答案1
關於您現有指示的一些注意事項:
重寫庫 /
雖然您已經定義了RewriteBase
,但它並未在您的任何指令中使用。只RewriteBase
適用於相對路徑替換(您已在相關指令中明確使用了根相對 URL 路徑)。
# Rewrites all URLS with example in them RewriteCond %{HTTP_HOST} ^(www\.)?example\.
你需要檢查請求的主機名稱?除非您託管多個網域(或子網域),並且您不想套用此規則,否則此狀態是多餘的。
# This works SOME of the time to redirect to https Header always set Content-Security-Policy "upgrade-insecure-requests;"
這絕不觸發“重定向”,所以我不確定您在網路流量中看到了什麼?
(事實上,您發布的程式碼中沒有任何內容會觸發從 HTTP 到 HTTPS 的「重定向」。)
此 HTTP 回應標頭使瀏覽器自動「升級」任何請求連結資源(CSS、JS、圖像、外部資源等)來自初始 HTML(頁面)回應,否則將透過 HTTP(例如,因為實際 URL 包含http://...
)透過 HTTPS。沒有實際的“重定向”發生。可能透過純 HTTP 傳輸的初始 HTML 回應沒有任何反應。
如果您已經實作了網站範圍的 HTTP 到 HTTPS 重新導向,並且所有連結的資源都已經是 HTTPS 或使用根相對(或協定相對)URL,則此標頭並不是絕對必要的。但它確實提供了一個良好的安全網。但請注意,任何不支援 HTTPS 的連結資源都會中斷 - 瀏覽器不會向使用者發出警告。如果沒有此標頭,使用者可能會收到瀏覽器「混合內容」警告(且連結的資源失敗)。
# If a request tries to access /joomla directly, redirect it to its secured canonical version RewriteCond %{THE_REQUEST} joomla/ RewriteRule ^joomla/(.*) http://example.com/$1 [R=301,L]
該RewriteCond
指令(用於防止“正常條件”下的重定向循環)與請求的 URL 中的任何位置匹配,甚至在查詢字串中 - 這是不正確的,如果應該出現在 URL 路徑的其他位置,甚至joomla/
可能會導致錯誤的重定向joomla/
查詢字串。例如,如果我只是附加?joomla/
到任何 URL 的末尾,這將導致重定向循環。
這個「重定向」應該去前內部重寫。一般來說,「重新導向」應該在「重寫」之前進行,以避免重新導向重寫的 URL 並將重寫的 URL 暴露給使用者。
如同評論中所指出的,此重定向是 HTTP - 與您嘗試執行的操作相反(並且在實現 HTTP 到 HTTPS 重定向時會導緻小型重定向鏈)。
一些假設:
- SSL憑證直接安裝在應用程式伺服器上,即。沒有 Cloudflare (Flexible-SSL) 或其他管理 SSL 的前端代理程式。
- 您沒有使用任何其他子網域。只是
www
。 - 規範主機名稱不是 www,即。
example.com
(來自您問題中的重定向)。 - 您目前尚未實作 HSTS,因此您可以
example.com
在單一重新導向中重新導向至 HTTPS 和規格主機名稱(即 )。 - Joomla 本身已配置為
/joomla
從 URL 中省略子目錄。/joomla
不存在於任何內部連結上,包括靜態資源(CSS、JS、圖像等)的鏈接 - 您沒有提供文檔根目錄中的任何文件。一切就是進入
/joomla
子目錄。
.htaccess
場景 #1 -文檔根目錄中的單一檔案。
(如評論中所述。)
.htaccess
在這種情況下,安裝子目錄 ( ) 中沒有「Joomla」檔案/joomla
可用於將 URL 路由至 Joomla 前端控制器(即index.php
)。在這種情況下,index.php
必須出現在 URL 中,且您不能使用 Joomla 的「SEF」URL。
根/.htaccess
文件看起來像這樣:
RewriteEngine on
RewriteBase /joomla
# If a request tries to access /joomla directly, redirect it to its secured canonical
RewriteCond %{THE_REQUEST} ^[A-Z]{3,7}\s/joomla
RewriteRule ^joomla(?:$|/(.*)) https://example.com/$1 [R=302,L]
# Canonicalise the hostname - ie. www to non-www and HTTPS
RewriteCond %{HTTP_HOST} ^www\.(.+?)\.?$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=302,L]
# Redirect remaining requests from HTTP to HTTPS
# The hostname must already be canonical at this point
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
# Rewrite everything to the /joomla subdirectory
# Uses the value defined in the RewriteBase directive above
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) $1 [L]
# Ensure that any linked resources are requested over HTTPS
Header always set Content-Security-Policy "upgrade-insecure-requests;"
請注意,出於測試目的,我在此處使用了 302(臨時)重定向。始終先使用 302 重定向進行測試,只有在確認可以正常工作後才變更為 301(永久)。 301 會被瀏覽器永久緩存,因此可能會為測試帶來問題。
環境REDIRECT_STATUS
變數用於確保我們只重寫直接請求而不重寫請求,與THE_REQUEST
第一條規則中使用的方式大致相同。REDIRECT_STATUS
在初始請求時為空,並在第一次成功重寫後設定為「200」(如 200 OK HTTP 回應狀態)。該指令RewriteRule (.*) $1 [L]
乍看之下可能有點奇怪(它看起來像是重寫為自身),但是, 是RewriteBase
結果替換的前綴,因此它實際上重寫為/joomla/<url>
.
場景 #2 - 兩個.htaccess
檔案:文檔根目錄和子目錄
.htaccess
子目錄中的檔案是/joomla
Joomla.htaccess
附帶的相當標準的檔案。這會將所有請求路由到 Joomla 前端控制器(即index.php
)並允許使用 Joomla 的「SEF」URL(即您不需要明確包含index.php
在 URL 中)。
根/.htaccess
文件看起來像這樣:
RewriteEngine on
RewriteBase /joomla
# Canonicalise the hostname - ie. www to non-www and HTTPS
RewriteCond %{HTTP_HOST} ^www\.(.+?)\.?$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=302,L]
# Redirect remaining requests from HTTP to HTTPS
# The hostname must already be canonical at this point
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
# Rewrite everything to the /joomla subdirectory
# Uses the value defined in the RewriteBase directive above
RewriteRule (.*) $1 [L]
# Ensure that any linked resources are requested over HTTPS
Header always set Content-Security-Policy "upgrade-insecure-requests;"
請注意,用於從 URL 中刪除子目錄的重定向/joomla
已被刪除,需要放入/joomla/.htaccess
檔案中。 (如果留在這裡就完全多餘了。)
REDIRECT_STATUS
這次您不需要檢查環境變量,因為您/joomla/.htaccess
願意抓住重寫後的請求。 (假設 mod_rewrite 繼承尚未啟用。)
如果您願意,可以將該Header
指令移至- 這是可選的,因為無論如何它都會被“繼承”。/joomla/.htaccess
然後,該/joomla/.htaccess
文件將包含以下內容:
# JOOMLA: Set Options here
RewriteEngine on
# If a request tries to access here directly then redirect back to root
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) https://example.com/$1 [R=302,L]
# JOOMLA: Rewrite rules to block out some common exploits.
# :
# Leave the RewriteBase directive commented out - it's not required
#RewriteBase /joomla
## Begin - Joomla! core SEF Section.
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
## End - Joomla! core SEF Section.
該/joomla/.htaccess
文件大致基於Joomla 網站上的程式碼但是,我省略了常見元素/註釋,並將“SEF 部分”更改為與子目錄相關。 (Joomla 也使用效率較低的正規表示式,.*
而不是簡單地使用^
.)