.htaccess 重寫 URL 並強制 https
網站:example.com
Joomla 子目錄:example.com/joomla
我希望在 example.com/joomla 上安裝的 Joomla 成為(或看起來是)網站的根目錄,即訪問 example.com 的人被重定向到 example.com/joompla/index.php 但仍然看到 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 重寫條件結合起來,因此我確信我錯過了邊緣場景。有更多經驗的人可以指導我完成這個嗎?這將不勝感激。幾天來,我一直在嘗試在網上找到的各種腳本,但還沒有完全找到神奇的詞。
關於您現有指令的一些注意事項:
RewriteBase /
雖然您已經定義了
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 響應標頭導致瀏覽器自動“升級”來自初始 HTML(頁面)響應的任何連結資源(CSS、JS、圖像、外部資源等)請求,否則該響應將通過 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
子目錄。場景 #1 -
.htaccess
文件根目錄中的單個文件。(如評論中所述。)
在這種情況下,安裝
.htaccess
子目錄/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
文件:文件根目錄和子目錄子目錄中的文件將是 Joomla 附帶的合理標准
.htaccess
文件。這會將所有請求路由到 Joomla 前端控制器(即。)並啟用 Joomla 的“SEF” URL(即,您不需要顯式包含在 URL 中)。/joomla``.htaccess``index.php``index.php
根
/.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
env var,因為它/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 也使用效率較低的正則表達式.*
而不是簡單的^
.)