詳解Asp.Net Core中的Cookies
目錄
- 詳解Asp.Net Core中的cookies
- 搞懂cookies
- Asp.Net中cookies的實現
- 從http中獲取cookies
- 將cookies寫入http中
- 總結及感想
詳解Asp.Net Core中的cookies
搞懂cookies
我之前寫過一篇文章來介紹cookies,如果你對cookies不是很了解請移步理解cookies這篇文章,這對於我們研究asp.net core中的cookies可以起到很大的幫助。
Asp.Net中cookies的實現
cookies是http協議中header頭的一部分,服務器與客戶端的cookies傳遞都是通過header頭完成的,那麽asp.net core只不過是對http協議的一種實現而已。
從http中獲取cookies
要從http中獲取cookies,首先我們要獲取header頭信息,而這部分信息asp.net core已經為我們準備好了,並且也幫我們解析了header頭中cookies,我們只需要通過HttpContext.Request.Cookies
就可以獲取所有的cookies信息。
接下來我們主要研究一下asp.net core是如何做的,在這裏語言是否顯得蒼白許多,我們盡量以貼代碼為主:
- 首先,我們從
HttpContext.Request.Cookies
對象下手
public abstract class HttpRequest { ... public abstract IRequestCookieCollection Cookies { get; set; } ... }
從代碼可以可看出Cookies是一個IRequestCookieCollection
接口類型,它的實現類型為RequestCookieCollection
,接口代碼如下:
//從接口代碼看該類是一個只讀類,為什麽會是只讀類,這也不難理解,Request是一個請求對象,也就是客戶端發往服務器的數據,因為這些數據是供我們來讀取驗證用的,所以修改並沒有什麽意義 public interface IRequestCookieCollection : IEnumerable<KeyValuePair<string, string>>, IEnumerable { string this[string key] { get; } int Count { get; } ICollection<string> Keys { get; } bool ContainsKey(string key); bool TryGetValue(string key, out string value); }
然後,我們再來分析header中的cookies是如何被解析到Request中的Cookies對象的
DefaultHttpRequest是如何實現HttpRequest的:
public class DefaultHttpRequest : HttpRequest { ... //這是一個委托對象,用於生成RequestCookiesFeature實例 private readonly static Func<IFeatureCollection, IRequestCookiesFeature> _newRequestCookiesFeature = f => new RequestCookiesFeature(f); ... //這個方法屬性展示了如何去實例化RequestCookiesFeature對象 private IRequestCookiesFeature RequestCookiesFeature =>_features.Fetch(ref _features.Cache.Cookies, _newRequestCookiesFeature); //這裏直接調用RequestCookiesFeature public override IRequestCookieCollection Cookies { get { return RequestCookiesFeature.Cookies; } set { RequestCookiesFeature.Cookies = value; } } }
RequestCookiesFeature.Cookies才是真正觸發cookies解析的地方:
public class RequestCookiesFeature : IRequestCookiesFeature { public IRequestCookieCollection Cookies { get { ... //從請求中獲取header信息,headers是一個IDictionary<string,StringValues>類型 var headers = HttpRequestFeature.Headers; StringValues current; //從headers字典類型中獲取cookies的信息,這裏獲取的current結果是個字符串類型 if (!headers.TryGetValue(HeaderNames.Cookie, out current)) { current = string.Empty; } if (_parsedValues == null || _original != current) { _original = current; //這裏開始將cookies字符串解析為cookies集合類型 _parsedValues = RequestCookieCollection.Parse(current.ToArray()); } } } //RequestCookieCollection.Parse代碼如下: public class RequestCookieCollection : IRequestCookieCollection { public static RequestCookieCollection Parse(IList<string> values) { ... IList<CookieHeaderValue> cookies; //最有用的一句代碼在這裏,將字符串集合解析為IList<CookieHeaderValue> if (CookieHeaderValue.TryParseList(values, out cookies)) { ... } ... } }
最終,CookieHeaderParser才是真正幹活的地方:
internal class CookieHeaderParser : HttpHeaderParser<CookieHeaderValue>
{
public sealed override bool TryParseValue(StringSegment value, ref int index, out CookieHeaderValue parsedValue)
{
...
}
}
將cookies寫入http中
我們先來看看Response.Cookies.Append是如何實現的
Response.Cookies是一個HttpRespnse對象,而ResponseCookies則是IResponseCookies的默認實現
public class ResponseCookies : IResponseCookies
{
//通過Append方法來添加cookie
public void Append(string key, string value)
{
//這裏構造一個cookie對象
var setCookieHeaderValue = new SetCookieHeaderValue(
Uri.EscapeDataString(key),
Uri.EscapeDataString(value))
{
Path = "/"
};
//然後cookie對象序列化字符串,因為在http協議中cookie的值就是字符串
var cookieValue = setCookieHeaderValue.ToString();
//最後將cookie字符串添加到Headers中,StringValues.Concat將兩個字符串轉換成string[]
//Headers是個字典類型,所有header中數據都是以k-v的形式保存在這個字典中
Headers[HeaderNames.SetCookie] = StringValues.Concat(Headers[HeaderNames.SetCookie], cookieValue);
}
看一下Headers的實現
HttpResponseHeaders負責將header信息寫入響應流
public partial class HttpResponseHeaders : HttpHeaders { internal void CopyTo(ref BufferWriter<PipeWriter> buffer) { //這個方將負責將headers通過流的形式寫入響應結果 CopyToFast(ref buffer); ... } }
總結及感想
? 本文介紹了,我對cookies的理解,以及asp.net core中cookies是怎麽實現的,對於所有web框架的實現都是大同小異的,如果還有什麽不明的地方最好自己能多讀幾遍代碼,多看多思考,最總一切問題都會迎刃而解。
詳解Asp.Net Core中的Cookies