1.Cookie概述
1.1.学习心得
本文不可能将cookie每个细节讲的面面俱到,学习亦是。本人觉得学习Cookie主要在于两大方面,一方面是运用二是安全方面,而不是一上来就死记硬背它的那些特点。运用方面需要实操演练cookie的细节特性,也就是本文中的“Cookie的关键项组成”章节中的五个属性并且要做到通过DEMO实际去验证该属性的一些特点,在深入领悟了其中的道理和相关的涉及面就可以很好的运用cookie;安全方面这块涉及到很多网络知识,我觉得作为程序员学习可以基本了解下,等到项目中紧密涉及到在进行深入,不然该方面会横向拓展涉及很多知识面,考虑到时间成本上并不划算。
1.2.简介Cookie
我理解最简单的一句话概括:一种可以用于客户端与服务器之间传输的数据存储功能,从而实现WEB的状态保持和会话跟踪。
并且该数据最终会以文本文件存放在客户端上,并且每个cookie存储数据量不能超过4KB。
在数据存储方面,cookie存储的是明文数据并且客户端是具备一些修改cookie的能力,所以不建议将敏感的数据存放在cookie中。
1.3存在的价值
和很多其他的保存WEB状态的对象一样,由于HTTP是一个无状态的协议,简单来比喻说:服务器中的WEB页面是没有记忆的,他记不住你来过还是第一次来,所以它需要借助一些类似存储性质的手段来实现记忆,当你来过时(状态),避免下次在来的时候做一些重复的工作(保持状态)。这一特性是每个WEB状态对象都具备的,然而在根据每个状态对象的细节特性可以运用实现不同的功能,如Cookie可以运用到“记住用户名”、“单点登录”等场景中。
1.4.Cookie之广告说
我们每个人可能都会经历如下一种场景,例如你在百度搜索了一些你感兴趣的东西(如手机)来了解一些详情资料,然后当你在去登录淘宝货京东之类的电商网站时他就会自动给你推送你曾经在百度上搜索的一些商品广告。这块的技术实现就使用到了Cookie,电商网站会根据在访问百度浏览时存储的cookie数据从而跟每个不同的人推送感兴趣的商品。
2.Cookie在客户端和服务器之间的交互
以一个记住用户名的一个运用场景绘制一个客户端浏览器和服务器的交互图:
在这个交互的过程中我们要记住以下:
1.关于报文
cookie的数据在传输过程中都放在在报文头中,当服务器创建cookie响应给浏览器时,cookie的内容是在响应报文的请求头中并在Set-Cooke属性中,这里还要强调一点是如果存在多个Cookie响应,那么Set-Cookie就存在多个;并且浏览器只要请求服务器就会将于服务器有关联的Cookie数据放在请求报文的请求头中,发送给服务器。
2.关于存储
Cookie执行的存储操作是一种物理形式,该操作是浏览器来完成的,服务器中创建的cookie只是组织数据告知浏览器来实际的执行。
3.Cookie的关键项组成
3.1.Name/Value属性
Cookie存储和读取数据都是以键值对的形式进行操作的,例如:Request.Cookies[“uid”]=”bob”;
Name即是键Value则是指。在存储数据时大多数浏览器对数据有大小的限制都在4KB以内,如果出现相同的键则后存储的会将上一个覆盖。
3.2.Expires属性
用于设置Cookie的到期时间,超过该时间cookie会失效。
根据该属性的设置与否,将cookie分为了两种性质:
第一种是会话性cookie,即没有设置该属性时,cookie的数据是保存在客户端的内存中,并且当用户关闭浏览器时cookie就失效。顾名思义,就像一段电话一样,电话打完了相关的语音即刻就断掉。
第二种是持久性cookie,即设置了该属性cookie有了指定失效的时间,此时的cookie的数据是保存在电脑的硬盘上,当到了失效时间或者用户手动通过浏览器清除时cookie在会失效。
Cookie的删除其实就是通过将该属性设置为一个已经过期的时间,从而浏览器会对cookie进行清除。
3.3.Path属性
用于设置某个Cookie允许访问的目录,例如你只想让此Cookie让网站下某个指定目录下代码页面进行访问,就可以设置该属性。默认的情况下也就是没有指定此属性时,设置的Cookie在对应的站点中所有页面均可访问。
这里还有一个细节需要注意,如果设置指定目录才能访问,那么浏览器在发送请求时除了指定目录会发送cookie,其他的页面浏览器不会发送cookie请求报文头中也不会存在cookie的数据。
实操验证:
示例说明:
通过请求Test.ahsx页面创建一个cookie并设置了指定允许访问的目录A,页面请求后浏览器接收到服务器返回的cookie在响应报文头中,接下来分别请求A目录和B目录的两个页面,由于cookie只允许A目录的页面才能访问,所以在请求A.ahsx页面时成功的输出了cookie中的数据,并观察到只有在请求A目录的页面时浏览器的请求报文中才会有cookie数据。
另外,通过设置该属性可以缩小访问的范围从而提高一定的安全性。
3.4.Domain属性
指定了可以访问该Cookie的域名,默认值是当前站点所在服务器的域。
简单来说cookie的访问不能跨域例如,www.baidu.com站点创建的cookie在www.sina.com站点中是不能访问的。
但是不能跨域不代表不能跨服务器或站点,因为域名可以指向多台服务器或多个不同的网站系统,因为cookie机制并未严格遵守同源策略,例如www.baidu.com:801站点创建的cookie可以在www.baidu.com:802站点中进行读取,然而此特性对于实现单点登录非常有用。
下图示例两个不同的站点共享cookie数据,因为两个站点都在同域下。
另外这里还补充一点:
上述说cookie不能跨域名访问,并且不能跨浏览器访问不同浏览器设置的cookie都是不相关的,例如你在谷歌浏览器在博客园上进行了登录,博客园使用cookie记录你的用户名,然后你在IE浏览器访问博客园此时IE不能获取你在谷歌浏览记住的用户名,需要重新输入。
3.4.Secure属性
指定是否使用HTTTPS安全协议发送Cookie。使用HTTP安全协议,可以保护Cookie在浏览器和Web服务器之间传输过程中不被窃取和篡改。个人觉得Domain属性的特性在一定范围上拓展了Cookie的使用范围但是会造成一定的安全隐患,最简单的方式就是将站点部署为HTTPS的站点并为Cookie设置该属性。
3.5HTTPOnly属性
用于防止客户端通过JS脚本document.cookie属性访问cookie,有助于保护Cookie不被跨站脚本攻击窃取或篡改。但是,HTTPOnly的应用仍存在局限性,一些浏览器可以被阻止使JS读取cookie,但允许写的操作;此外大多数浏览器仍允许通过XMLHTTP对象读取HTTP响应中的Set-Cookie头从而获取cookie数据,个人觉得该属性的存在没有太大的实际意义。
4.在ASP.NET中使用Cookie
使用Cookie很简单,也根本不用记住,还是秉承着“要什么点什么”的原则就行,如:Request.Cookies。
下面还是官方的写下代码:
1 HttpCookie cookieUid = Request.Cookies["uid"];
2
3 if (cookieUid==null) //第一次访问,则创建
4 {
5 cookieUid = new HttpCookie("uid", Request["uid"]);
6 cookieUid.Expires = DateTime.Now.AddDays(1);
7 }
8 else // 非第一次,则直接读取
9 {
10 string uid = cookieUid.Value;
11 Response.Write("当前登录用户名:"+uid);
12 }
在写代码时需要注意:
- ASP.NET在代码组织中将Cookie分为两种,一种是客户端请求的,另一种是服务器响应的,也就是:Request.Cookies和Response.Cookie。在向浏览器发送Cookie时,不要将Response.Cookie写成Request.Cookies,否则会导致cookie创建失败。
- 在写Cookie一定要考虑设置有效期,如果没有设置那么该cookie的有效期,那这就属于一个会话性Cookie,在浏览器关闭时Cookie就会销毁。