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

ASP.NET 客戶端狀態管理完整比較指南

     編輯:關於ASP.NET

HTTP 無狀態本質與解決方案

HTTP 協定本身無狀態,每次請求獨立。ASP.NET 提供多種客戶端狀態管理機制,各有優缺點與適用場景:

五大機制詳細比較

機制儲存位置容量限制安全性生命週期適用場景
Cookie客戶端硬碟/記憶體4KB/個, 20-50個/域可加密, 但可被竄改可設定過期時間使用者偏好、記住登入、追蹤 ID
QueryStringURL 參數~2KB (IE 限制)明文, 易被竄改單次請求頁面間傳遞非敏感參數、分頁、搜尋條件
Hidden Field表單隱藏欄位無明確限制明文, 可被檢視原始碼單次 Postback頁面內暫存資料、表單驗證 Token
ViewState頁面隱藏欄位 (__VIEWSTATE)視頁面複雜度, 易膨脹可啟用 MAC 驗證/加密頁面生命週期控制項狀態自動保持 (GridView 分頁、輸入值)
ControlState頁面隱藏欄位極小 (僅必要資料)不可關閉, 內建保護頁面生命週期自訂控制項核心功能資料 (如 GridView 排序欄位)

Cookie 實作範例

寫入 Cookie

// 簡單寫入
Response.Cookies["UserName"].Value = "JohnDoe";
Response.Cookies["UserName"].Expires = DateTime.Now.AddDays(30);

// 安全寫入 (HttpOnly + Secure + SameSite)
var cookie = new HttpCookie("AuthToken", token) {
    HttpOnly = true,           // 防止 XSS 竊取
    Secure = true,             // 僅 HTTPS 傳輸
    SameSite = SameSiteMode.Strict, // 防止 CSRF
    Expires = DateTime.Now.AddHours(2)
};
Response.Cookies.Add(cookie);

讀取 Cookie

if (Request.Cookies["UserName"] != null) {
    string user = Request.Cookies["UserName"].Value;
    lblWelcome.Text = $"歡迎回來, {HttpUtility.HtmlEncode(user)}!";
}

ViewState 深度解析

啟用/停用控制

<!-- 頁面層級 -->
<%@ Page EnableViewState="false" %>

<!-- 控制項層級 -->
<asp:GridView ID="gvData" EnableViewState="true" />
<asp:Label ID="lblStatic" EnableViewState="false" />

ViewState 壓縮 (自訂 PageStatePersister)

public class CompressedViewStatePersister : PageStatePersister {
    public CompressedViewStatePersister(Page page) : base(page) { }

    public override void Load() {
        var input = new MemoryStream(Convert.FromBase64String(
            Page.Request.Form["__COMPRESSED_VIEWSTATE"]));
        using (var gzip = new GZipStream(input, CompressionMode.Decompress))
        using (var reader = new BinaryReader(gzip)) {
            ViewState = reader.ReadObject();
            ControlState = reader.ReadObject();
        }
    }

    public override void Save() {
        using (var output = new MemoryStream())
        using (var gzip = new GZipStream(output, CompressionMode.Compress))
        using (var writer = new BinaryWriter(gzip)) {
            writer.WriteObject(ViewState);
            writer.WriteObject(ControlState);
            Page.ClientScript.RegisterHiddenField(
                "__COMPRESSED_VIEWSTATE", Convert.ToBase64String(output.ToArray()));
        }
    }
}

// 在 Page 類別覆寫
protected override PageStatePersister PageStatePersister 
    => new CompressedViewStatePersister(this);

ControlState 實作 (自訂控制項)

public class PagerControl : WebControl {
    private int _currentPage = 1;

    protected override void OnInit(EventArgs e) {
        base.OnInit(e);
        Page.RegisterRequiresControlState(this);
    }

    protected override void LoadControlState(object savedState) {
        _currentPage = (int)savedState;
    }

    protected override object SaveControlState() {
        return _currentPage;
    }
}

安全性最佳實踐

  1. 敏感資料勿存客戶端:密碼、信用卡、個人身分證號絕對不可放入 Cookie/ViewState
  2. 啟用 ViewStateMAC:<pages enableViewStateMac="true"> (預設開啟)
  3. 加密 ViewState:<pages viewStateEncryptionMode="Auto"> (需機器金鑰一致)
  4. Cookie 設定 HttpOnly + Secure:防止 XSS 與中間人攻擊
  5. 使用 SameSite Cookie:SameSite=Strict/Lax 防禦 CSRF
  6. 驗證所有輸入:QueryString、Hidden Field、Cookie 值皆視為不可信

選擇決策樹

需要跨頁面/跨工作階段保持?
  ├─ 是 → 資料敏感?
  │       ├─ 是 → 伺服端 Session/資料庫 + 客戶端只存 SessionID
  │       └─ 否 → Cookie (設定適當過期時間)
  └─ 單一頁面/Postback 內?
          ├─ 控制項自動狀態 → ViewState (預設)
          ├─ 自訂控制項核心邏輯 → ControlState
          ├─ 表單暫存資料 → Hidden Field
          └─ 導航/分頁參數 → QueryString
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved