[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框架的实现都是大同小异的,若是还有什么不明的地方最好本身能多读几遍代码,多看多思考,最总一切问题都会迎刃而解。