詳解Asp.Net Core中的Cookies


詳解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是如何做的,在這里語言是否顯得蒼白許多,我們盡量以貼代碼為主:

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框架的實現都是大同小異的,如果還有什么不明的地方最好自己能多讀幾遍代碼,多看多思考,最總一切問題都會迎刃而解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM