首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 與傳統 ASP 中文 Cookie 互通解決方案:編碼差異分析與雙向相容代碼

     編輯:ASP.NET 基礎

問題背景

企業系統遷移期常面臨 **ASP.NET (UTF-8)** 與 **傳統 ASP (GB2312/Big5)** 共存,需共享登入狀態 (Cookie)。預設情況下:

  • ASP.NET `HttpUtility.UrlEncode` 預設 **UTF-8** 編碼中文。
  • 傳統 ASP `Server.URLEncode` 預設 **系統代碼頁** (中文環境通常為 GB2312/CP936)。
  • 導致雙方寫入/讀取中文 Cookie 時出現亂碼。

核心解決原則

統一雙方對中文 Cookie Value 的編碼格式為 GB2312 (或雙方協商的編碼),並在讀寫時顯式指定編碼。

方案一:ASP.NET 寫入 GB2312 編碼 Cookie (讓 ASP 能正確讀取)

// C# (ASP.NET)
public static void WriteCookie(string cookieName, string key, string value)
{
    // 1. 取得 GB2312 編碼器
    Encoding gb2312 = Encoding.GetEncoding("GB2312"); // 或 "CP936"

    // 2. 使用 GB2312 進行 UrlEncode
    string encodedValue = HttpUtility.UrlEncode(value, gb2312);

    // 3. 寫入 Cookie
    HttpContext.Current.Response.Cookies[cookieName][key] = encodedValue;
    
    // 可選:設定 Domain/Path/Expires 確保跨應用程式存取
    // HttpContext.Current.Response.Cookies[cookieName].Domain = ".example.com";
}

方案二:ASP.NET 讀取 GB2312 編碼 Cookie (正確顯示中文)

// C# (ASP.NET)
public static string ReadCookie(string cookieName, string key)
{
    var cookie = HttpContext.Current.Request.Cookies[cookieName];
    if (cookie == null || cookie[key] == null) return null;

    string encodedValue = cookie[key];
    
    // 1. 先用預設 (UTF-8) UrlDecode 一次 (因為 Request 會自動 UrlDecode 一次)
    // 注意:ASP.NET Request 會自動對 Cookie Value 做 UrlDecode (預設 UTF-8)
    // 所以我們拿到的已經是「UTF-8 解碼後的 GB2312 位元組序列轉字串」-> 亂碼字串
    // 2. 將此亂碼字串還原為位元組 (用 ISO-8859-1 或 Default 反向)
    // 3. 再用 GB2312 正確解碼
    
    // 簡化版:直接用 GB2312 UrlDecode (ASP.NET 4.5+ HttpUtility 支援指定編碼解碼)
    Encoding gb2312 = Encoding.GetEncoding("GB2312");
    return HttpUtility.UrlDecode(encodedValue, gb2312);
    
    // 若版本不支援,手動還原:
    // byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(encodedValue);
    // return gb2312.GetString(bytes);
}

方案三:傳統 ASP 讀寫 GB2312 Cookie (原生相容)

' VBScript (Classic ASP)
' 寫入 - ASP 原生即為 GB2312 (系統代碼頁)
Response.Cookies(cookieName)(key) = Server.URLEncode(value) ' value 為 GB2312 字串

' 讀取
Dim val
val = Request.Cookies(cookieName)(key)
If Not IsEmpty(val) Then
    val = Server.URLDecode(val) ' 解碼為 GB2312 字串
End If

方案四:統一修改 ASP.NET 全域編碼 (不推薦,副作用大)

<!-- web.config -->
<system.web>
    <globalization requestEncoding="GB2312" responseEncoding="GB2312" fileEncoding="GB2312" />
</system.web>

缺點:影響整個應用程式的請求/回應/檔案讀寫編碼,可能導致資料庫存取、前端頁面、API 介接等全線亂碼,**強烈不建議** 除非整個專案純中文且無外部整合。

完整雙向相容輔助類

using System;
using System.Text;
using System.Web;

public static class CrossPlatformCookieHelper
{
    // 協商編碼:GB2312 (相容 ASP) 或 UTF-8 (現代標準,需 ASP 端配合)
    private static readonly Encoding _cookieEncoding = Encoding.GetEncoding("GB2312");
    private const string CookieDomain = ".yourdomain.com"; // 設定共同根域名

    /// 寫入跨平台相容 Cookie
    public static void SetCookie(string name, string key, string value, DateTime? expires = null, string path = "/")
    {
        var cookie = new HttpCookie(name)
        {
            Domain = CookieDomain,
            Path = path,
            HttpOnly = true,
            Secure = HttpContext.Current.Request.IsSecureConnection // HTTPS 時自動 Secure
        };

        if (expires.HasValue) cookie.Expires = expires.Value;

        // 關鍵:使用協商編碼 UrlEncode
        cookie[key] = HttpUtility.UrlEncode(value, _cookieEncoding);

        HttpContext.Current.Response.Cookies.Set(cookie);
    }

    /// 讀取跨平台相容 Cookie
    public static string GetCookie(string name, string key)
    {
        var cookie = HttpContext.Current.Request.Cookies[name];
        if (cookie == null || cookie[key] == null) return null;

        // 關鍵:使用協商編碼 UrlDecode
        return HttpUtility.UrlDecode(cookie[key], _cookieEncoding);
    }

    /// 刪除 Cookie (跨平台通用)
    public static void RemoveCookie(string name, string path = "/")
    {
        var cookie = new HttpCookie(name)
        {
            Domain = CookieDomain,
            Path = path,
            Expires = DateTime.Now.AddDays(-1),
            Value = ""
        };
        HttpContext.Current.Response.Cookies.Set(cookie);
    }

    /// 清除所有 Cookie (含 Session)
    public static void ClearAllCookies()
    {
        // 1. 清除 Request Cookies 集合 (避免迭代修改集合)
        var keys = HttpContext.Current.Request.Cookies.AllKeys;
        foreach (var key in keys)
        {
            RemoveCookie(key);
        }
        // 2. 明確清除 Response 集合
        HttpContext.Current.Response.Cookies.Clear();
        // 3. 終結 Session
        HttpContext.Current.Session?.Abandon();
    }
}

常見坑點與驗證清單

現象原因驗證/修正
ASP.NET 寫入後 ASP 讀取亂碼ASP.NET 用 UTF-8 編碼,ASP 用 GB2312 解碼ASP.NET 強制用 GB2312 `UrlEncode`
ASP 寫入後 ASP.NET 顯示亂碼ASP.NET Request 自動用 UTF-8 UrlDecodeASP.NET 用 GB2312 `UrlDecode` 手動修正
跨子域名無法共享Cookie Domain 未設定為共同根域名雙方設 `Domain = ".example.com"`
HTTPS 下 Cookie 不傳送未設 Secure 標記 / SameSite 政策設 `Secure = true`,SameSite=Lax/None
清除 Cookie 後 ASP 仍讀到舊值未呼叫 `Response.Cookies.Clear()` 或路徑/域名不匹配同 Domain/Path 設 Expires 為過去時間 + `Response.Cookies.Clear()`

現代化建議:棄用 Cookie 傳遞中文,改用 Token + 共享 Session/Redis

  1. 登入後簽發 **JWT** 或 **Guid Token**,存放於 **HttpOnly Cookie** (僅存 Token,無中文)。
  2. ASP.NET 與 ASP 共用 **Redis** 或 **資料庫 Session 表**,以 Token 為 Key 存取使用者資料 (含中文)。
  3. 徹底避開編碼地獄,且安全性、擴展性更佳。

總結

ASP.NET 與 ASP 中文 Cookie 互通的核心在於 **雙方協商統一編碼 (建議 GB2312)** 並在讀寫時 **顯式指定編碼**。提供的 `CrossPlatformCookieHelper` 可直接納入專案解決歷史包袱。長遠規劃應遷移至 Token + 共享 Session 架構,從根本消除編碼相容性問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved