zoukankan      html  css  js  c++  java
  • 详解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框架的实现都是大同小异的,如果还有什么不明的地方最好自己能多读几遍代码,多看多思考,最总一切问题都会迎刃而解。

  • 相关阅读:
    Java初学者笔记四:按行读写文件和输入处理
    Java初学者笔记三:关于字符串和自实现数组常见操作以及异常处理
    Java初学者笔记二:关于类的常见知识点汇总
    python的类继承与派生
    Java初学者笔记一:元类、获取类型、枚举
    Tomcat远程任意代码执行漏洞及其POC(CVE-2017-12617)
    PostgreSQL远程代码执行漏洞(CVE-2018-1058)学习笔记
    python的三个函数(eval、exec、complie)和python版RMI
    关于Memcached反射型DRDoS攻击分析
    python的其他安全隐患
  • 原文地址:https://www.cnblogs.com/guodf/p/9609384.html
Copyright © 2011-2022 走看看