
所以我有這個 apache 配置,我試圖將使用者「重寫」到自訂錯誤頁面,但它不起作用。我在瀏覽器中輸入http://localhost/index.html/ddgdg%:sdsdfs
,但沒有收到錯誤頁面。
我可以透過直接在瀏覽器中輸入其 URL 來查看自訂錯誤頁面 ( http://localhost/my-error.html
)。
有什麼想法我可能做錯了什麼嗎?
我的完整 httpd.conf:連結到 httpd.conf
我對預設 httpd.conf 的更改(我還必須取消註釋 mod_rewrite.so 的 LoadModule)
RewriteEngine On
LogLevel alert rewrite:info
#if invalid characters are present in the URI, display 404 page
RewriteCond %{REQUEST_URI} ^\/.+[:%].+
RewriteRule "^/$" "http://%{SERVER_NAME}/my-error.html" [L,R=301]
自訂錯誤頁面的內容
$ cat /Library/WebServer/Documents/my-error.html
<html><body><h1>404 error here</h1></body></html>
阿帕契版本
$ apachectl -v
Server version: Apache/2.4.34 (Unix)
Server built: Feb 22 2019 20:20:11
編輯1:目前正在運行 macOS Mojave,但稍後將設定 Ubuntu VM。
答案1
這裡發生了一些不同的問題...
http://localhost/index.html/ddgdg%:sdsdfs
你其實並沒有說明你得到了什麼回應,只是說明了什麼沒有發生。然而,由於雜散%
(不在十六進位編碼的八位元組之前),該 URL 完全無效,我希望 Apache 能夠以400 Bad Request
.覆蓋此問題的唯一方法是建立自訂 400 錯誤文檔,您可以在其中檢查請求的 URL 並自訂回應。例如:
ErrorDocument 400 /my-error.html
如果不是流浪者,%
您應該能夠使用 mod_rewrite 捕獲此請求並相應地重定向。但是,您RewriteRule
正在檢查空 URL 路徑(即"^/$"
),而範例中請求的 URL 遠非空(即/index.html/ddgdg%:sdsdfs
) - 因此該RewriteRule
指令永遠不會與您的範例 URL 相符。若要檢查URL 路徑中的%
或:
任意位置並重新導向,您可以執行以下操作:
# Checks for a "%" or ":" in the URL-path
RewriteRule [%:] /my-error.html [L,R=302]
但請注意,URL 路徑匹配RewriteRule
圖案(以及REQUEST_URI
伺服器變數)已經%解碼,因此這只會匹配特殊字元已被雙重編碼的URL(罕見)。 (如上所述,否則流浪%
可能會產生 400 回應前mod_rewrite 能夠處理該請求。
我還想問為什麼您想要“重定向”到您的自訂錯誤文件(即my-error.html
)而不直接提供它?重定向有許多缺點:發送到客戶端的 3xx 回應、丟失有關導致錯誤的 URL 的資訊、對伺服器的請求加倍等。
你可以內部重寫透過簡單地刪除標誌來將請求發送到/my-error.html
,而不是重定向R
。例如:
RewriteRule [%:] /my-error.html [L]
但是,除非您手動設定 HTTP 狀態,否則my-error.html
使用者將看到200 OK
回應 - 這是不可取的。
或者(最好)建立自訂 404(看起來像您正在嘗試執行的操作)並觸發它。例如:
ErrorDocument 404 /my-error.html
RewriteRule [%:] - [R=404]
然後 Apache 設定「404 Not Found」HTTP 回應狀態。
但是,您可能根本不需要在這裡使用 mod_rewrite。在您的範例 URL 中,index.html
URL 路徑中後面的所有內容(即 )/ddgdg%:sdsdfs
是附加路徑名資訊(又稱路徑資訊 / PATH_INFO
)。預設情況下,處理 text/html 回應的處理程序不允許路徑訊息,並且將隱式觸發 404(如果不是流浪%
- 如上所述),調用您的自訂ErrorDocument
(如果已定義)。因此,RewriteRule
可以簡單地刪除最後一個範例中的指令,因為 Apache 無論如何都會觸發 404(除非您使用 覆寫此行為AcceptPathInfo
)。