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

ASP.NET Cookie 讀寫處理流程深度剖析:從請求頭到響應頭的完整鏈路

     編輯:ASP.NET 基礎

Cookie 基礎回顧

Cookie 由伺服器設定(Set-Cookie 響應頭),瀏覽器自動攜帶(Cookie 請求頭)於後續請求。ASP.NET 封裝了完整的讀寫機制,本文追溯源碼級實現。

請求端:HttpRequest.Cookies 獲取流程

1. 入口屬性

public HttpCookieCollection Cookies {
    get { EnsureCookies(); return _cookies; }
}

2. EnsureCookies 初始化

internal HttpCookieCollection EnsureCookies() {
    if (_cookies == null) {
        _cookies = new HttpCookieCollection(null, false);
        if (_wr != null) FillInCookiesCollection(_cookies, true);
        if (HasTransitionedToWebSocketRequest) _cookies.MakeReadOnly();
    }
    return _cookies;
}

3. FillInCookiesCollection 核心解析

internal void FillInCookiesCollection(HttpCookieCollection cookieCollection, bool includeResponse) {
    // 1. 從 HttpWorkerRequest 獲取原始 Cookie 字符串
    String s = _wr.GetKnownRequestHeader(HttpWorkerRequest.HeaderCookie);
    
    // 2. 按分號分割解析每個 Cookie
    // 格式: name=value; name2=value2; ...
    // 支援子鍵: name=key1=val1&key2=val2
    
    // 3. 處理 $Path、$Domain 等屬性前綴
    
    // 4. 合併響應端已設定的 Cookie (includeResponse=true)
}

4. 底層獲取:ISAPIWorkerRequest.GetKnownRequestHeader

  • 最終調用 GetServerVariable("ALL_RAW") 獲取原始 HTTP 頭
  • IIS 7/6/5 不同實現類繼承鏈:ISAPIWorkerRequestInProcForIIS7 → ... → HttpWorkerRequest

5. CreateCookieFromString:字符串轉 HttpCookie 實例

解析 name=value 或 name=key1=val1&key2=val2 格式,填充 HttpCookie.Values 集合。

6. 請求驗證:ValidateCookieCollection

private void ValidateCookieCollection(HttpCookieCollection cc) {
    // 預設啟用請求驗證,防 XSS 注入
    // 呼叫 RequestValidator.Current.IsValidRequestString
    // 支援粒度驗證:按需驗證而非全量驗證
}

響應端:HttpResponse.Cookies 寫入流程

1. HttpCookie 核心屬性

  • Name/Value、Domain/Path、Expires、Secure/HttpOnly、Shareable(影響輸出緩存)
  • 內部標記:_changed、_added、FromHeader

2. GetSetCookieHeader:生成 Set-Cookie 頭字符串

internal HttpResponseHeader GetSetCookieHeader(HttpContext context) {
    StringBuilder s = new StringBuilder();
    s.Append(Name).Append('=');
    // 值處理:支援多值集合
    if (_multiValue != null) s.Append(_multiValue.ToString(false));
    else if (_stringValue != null) s.Append(_stringValue);
    
    // 屬性序列化
    if (!String.IsNullOrEmpty(_domain)) s.Append("; domain=").Append(_domain);
    if (_expirationSet) s.Append("; expires=").Append(HttpUtility.FormatHttpCookieDateTime(_expires));
    if (!String.IsNullOrEmpty(_path)) s.Append("; path=").Append(_path);
    if (_secure) s.Append("; secure");
    if (_httpOnly && SupportsHttpOnly(context)) s.Append("; HttpOnly");
    
    return new HttpResponseHeader(HttpWorkerRequest.HeaderSetCookie, s.ToString());
}

3. HttpCookieCollection.AddCookie:集合管理

internal void AddCookie(HttpCookie cookie, bool append) {
    // 檢查最大鍵數限制
    // append=true:BaseAdd(新增/覆蓋),標記 Added=true
    // append=false:BaseSet(強制覆蓋),標記 Changed=true
}

4. HttpResponse.AppendCookie / Cookies.Add 統一入口

  • 檢查 _headersWritten:若已發送響應頭則拋異常「Cannot modify cookies after headers sent」
  • 呼叫 OnCookieAdd 同步至 HttpRequest._cookies 與 _params

5. GenerateResponseHeadersForCookies:響應頭生成策略

internal void GenerateResponseHeadersForCookies() {
    // 情況一:僅有新增 Cookie → 直接輸出新 Set-Cookie 頭
    // 情況二:有修改/刪除 Cookie → 清除所有 Set-Cookie 頭,重寫全部
    // IIS 限制:無法刪除特定 Set-Cookie 頭,必須全量重寫
}

關鍵檢查點總結

階段檢查項異常/行為
讀取請求請求驗證RequestValidator 驗證 Cookie 值
寫入響應Cookie 數量上限超過 MaxHttpCollectionKeys 拋異常
寫入響應響應頭是否已發送_headersWritten=true 禁止修改
生成頭是否需全量重寫有修改/刪除時清除重寫所有

結語

ASP.NET Cookie 機制本質是:請求端解析 HTTP_COOKIE 頭 → 驗證 → HttpCookieCollection;響應端管理 HttpCookie 狀態 → 生成 Set-Cookie 頭 → 寫入響應頭集合。理解此流程有助於診斷「Cookie 丟失」「headers sent 錯誤」「跨域 Cookie 不生效」等疑難雜症。

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