[TOC]html
我以前寫過一篇文章來介紹cookies,若是你對cookies不是很瞭解請移步理解cookies這篇文章,這對於咱們研究asp.net core中的cookies能夠起到很大的幫助。git
cookies是http協議中header頭的一部分,服務器與客戶端的cookies傳遞都是經過header頭完成的,那麼asp.net core只不過是對http協議的一種實現而已。github
要從http中獲取cookies,首先咱們要獲取header頭信息,而這部分信息asp.net core已經爲咱們準備好了,而且也幫咱們解析了header頭中cookies,咱們只須要經過HttpContext.Request.Cookies
就能夠獲取全部的cookies信息。web
接下來咱們主要研究一下asp.net core是如何作的,在這裏語言是否顯得蒼白許多,咱們儘可能以貼代碼爲主:服務器
HttpContext.Request.Cookies
對象下手public abstract class HttpRequest { ... public abstract IRequestCookieCollection Cookies { get; set; } ... }
從代碼能夠可看出Cookies是一個IRequestCookieCollection
接口類型,它的實現類型爲RequestCookieCollection
,接口代碼以下:cookie
//從接口代碼看該類是一個只讀類,爲何會是隻讀類,這也不難理解,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的:asp.net
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解析的地方:ide
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纔是真正幹活的地方:this
internal class CookieHeaderParser : HttpHeaderParser<CookieHeaderValue> { public sealed override bool TryParseValue(StringSegment value, ref int index, out CookieHeaderValue parsedValue) { ... } }
咱們先來看看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框架的實現都是大同小異的,若是還有什麼不明的地方最好本身能多讀幾遍代碼,多看多思考,最總一切問題都會迎刃而解。