.htaccess 進行 URL 重寫並強制使用 https

.htaccess 進行 URL 重寫並強制使用 https

網址: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} !=onRewriteCond %{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子目錄中的檔案是/joomlaJoomla.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 也使用效率較低的正規表示式,.*而不是簡單地使用^.)

相關內容