`Request.UrlReferrer` 回傳 `Uri` 物件,其 `Query` 屬性已自動 **URL 解碼**。若原始 Referer URL 含中文參數且瀏覽器編碼非 UTF-8 (如舊版 IE 送 GB2312),`Uri` 解碼時預設用 UTF-8 導致亂碼。**直接對完整 URL `UrlEncode` 無效**,因路徑部分不需編碼且會破壞結構。
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string refererUrl = Request.UrlReferrer?.ToString();
if (!string.IsNullOrEmpty(refererUrl))
{
// 1. 分割路徑與查詢字串
var uri = new Uri(refererUrl);
string path = uri.GetLeftPart(UriPartial.Path); // 含 scheme://host/path
string query = uri.Query; // 含前導 '?',已被錯誤解碼
// 2. 將查詢字串按原始位元組重新編碼為 GB2312 (或目標編碼)
// 關鍵:先取得錯誤解碼後的字串對應的位元組 (預設 UTF-8 解碼產生的位元組)
// 再按正確編碼 (GB2312) 解碼回字串,最後再 UrlEncode
// 簡化做法:假設瀏覽器原始送 GB2312,伺服器誤用 UTF-8 解碼
// 實際專案建議統一全站 UTF-8,避免此問題
byte[] utf8Bytes = Encoding.UTF8.GetBytes(query);
string correctedQuery = Encoding.GetEncoding("GB2312").GetString(utf8Bytes);
// 3. 重新 UrlEncode (UTF-8) 供後續安全使用
string safeQuery = HttpUtility.UrlEncode(correctedQuery, Encoding.UTF8);
string safeReferer = path + safeQuery;
ViewState["SafeReferer"] = safeReferer;
}
}
}
Response.Redirect(HttpUtility.UrlDecode(ViewState["SafeReferer"]?.ToString() ?? "~/Default.aspx"));
protected void Page_Load(object sender, EventArgs e)
{
try
{
// 若使用者手動修改網址列參數並 Enter,Referer 通常為 null 或無 Query
var _ = Request.UrlReferrer.PathAndQuery; // 觸發存取
}
catch
{
// Referer 為 null 導致 NullReferenceException
throw new InvalidOperationException("非法操作:請勿手動修改網址參數。");
}
}
**原理**:正常連結導航 → `Request.UrlReferrer` 含完整 `PathAndQuery`。手動修改網址列 → 瀏覽器不送 Referer 或送空 → `Request.UrlReferrer` 為 `null` → 存取屬性拋出例外。
**注意**:此法屬「偏門」,Referer 可被防火牆/隱私擴充/代理移除,誤判率高。**正規做法**:
`Request.UrlReferrer` 中文亂碼核心在於 **瀏覽器編碼與伺服器解碼不一致**。**分段編碼法** (路徑不動、Query 重編) 可修補舊系統;**全站統一 UTF-8** 為根治之道。安全防篡改請採用 **簽名/Token/權限檢查** 正規手段,勿依賴 Referer 側寫。