Asp.net cookie的处理流程深入分析

一说到Cookie我想大家都应该知道它是一个保存在客户端,当浏览器请求一个url时,浏览器会携带相关的Cookie达到服务器端,所以服务器是可以操作Cookie的,在Response时,会把Cookie信息输出到客服端。下面我们来看一个demo吧,代码如下:

Asp.net cookie的处理流程深入分析

第一次请求结果如下:

Asp.net cookie的处理流程深入分析

第二次请求结果如下:

Asp.net cookie的处理流程深入分析

到这里我们可以看到第二次请求传入的Cookie正好是第一次请求返回的Cookie信息,这里的cookie信息的维护主要是我们客户端的浏览器,但是在Asp.net程序开发时,Cookie往往是在服务端程序里面写入,就如我的事例代码;很少有用客服端js实现的。现在我们就来看看asp.net服务端是如何实现读写Cookie的。

首先我们来看看HttpRequest的Cookie是如何定义的:

复制代码 代码如下:


public HttpCookieCollection Cookies {
get {
EnsureCookies();
if (_flags[needToValidateCookies]) {
_flags.Clear(needToValidateCookies);
ValidateCookieCollection(_cookies);
}
return _cookies;
}
}


这里的Cookie获取主要是调用一个EnsureCookies方法,EnsureCookies放主要是调用

复制代码 代码如下:


// Populates the Cookies property but does not hook up validation.
internal HttpCookieCollection EnsureCookies() {
if (_cookies == null) {
_cookies = new HttpCookieCollection(null, false);
if (_wr != null)
FillInCookiesCollection(_cookies, true /*includeResponse*/);

if (HasTransitionedToWebSocketRequest) // cookies can't be modified after the WebSocket handshake is complete
_cookies.MakeReadOnly();
}
return _cookies;
}

public sealed class HttpCookieCollection : NameObjectCollectionBase
{
internal HttpCookieCollection(HttpResponse response, bool readOnly) : base(StringComparer.OrdinalIgnoreCase)
{
this._response = response;
base.IsReadOnly = readOnly;
}
}


其中这里的FillInCookiesCollection方法实现也比较复杂:

复制代码 代码如下:


internal void FillInCookiesCollection(HttpCookieCollection cookieCollection, bool includeResponse) {
if (_wr == null)
return;

String s = _wr.GetKnownRequestHeader(HttpWorkerRequest.HeaderCookie);

// Parse the cookie server variable.
// Format: c1=k1=v1&k2=v2; c2=...

int l = (s != null) ? s.Length : 0;
int i = 0;
int j;
char ch;

HttpCookie lastCookie = null;

while (i < l) {
// find next ';' (don't look to ',' as per 91884)
j = i;
while (j < l) {
ch = s[j];
if (ch == ';')
break;
j++;
}

// create cookie form string
String cookieString = s.Substring(i, j-i).Trim();
i = j+1; // next cookie start

if (cookieString.Length == 0)
continue;

HttpCookie cookie = CreateCookieFromString(cookieString);

// some cookies starting with '$' are really attributes of the last cookie
if (lastCookie != null) {
String name = cookie.Name;

// add known attribute to the last cookie (if any)
if (name != null && name.Length > 0 && name[0] == '$') {
if (StringUtil.EqualsIgnoreCase(name, "$Path"))
lastCookie.Path = cookie.Value;
else if (StringUtil.EqualsIgnoreCase(name, "$Domain"))
lastCookie.Domain = cookie.Value;

continue;
}
}

// regular cookie
cookieCollection.AddCookie(cookie, true);
lastCookie = cookie;

// goto next cookie
}

// Append response cookies
if (includeResponse) {
// If we have a reference to the response cookies collection, use it directly
// rather than going through the Response object (which might not be available, e.g.
// if we have already transitioned to a WebSockets request).
HttpCookieCollection storedResponseCookies = _storedResponseCookies;
if (storedResponseCookies == null && !HasTransitionedToWebSocketRequest && Response != null) {
storedResponseCookies = Response.GetCookiesNoCreate();
}

if (storedResponseCookies != null && storedResponseCookies.Count > 0) {
HttpCookie[] responseCookieArray = new HttpCookie[storedResponseCookies.Count];
storedResponseCookies.CopyTo(responseCookieArray, 0);
for (int iCookie = 0; iCookie < responseCookieArray.Length; iCookie++)
cookieCollection.AddCookie(responseCookieArray[iCookie], append: true);
}

// release any stored reference to the response cookie collection
_storedResponseCookies = null;
}
}


说简单一点它主要调用HttpWorkerRequest的GetKnownRequestHeader方法获取浏览器传进来的Cookie字符串信息,然后再把这些信息根据;来分隔成多个HttpCookie实例。把这些HttpCookie实例添加到传进来的HttpCookieCollection参数。

这里HttpWorkerRequest继承结果如下:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjdfjp.html