Cookie 没你不行
Cookie 没你不行
前言:
你知道吗,当有人悄悄的禁用了你浏览器的cookie,一场灾难将会发生,如果你不是一个开发人员,那更是灾难。
笔者在写这篇文章前做了下实验,BAT全部登录不了,只有baidu给了个人性化的提示:
既然cookie如此重要,你真的对它了解吗?
Cookie 是什么
起源
讲这个还是得先讲讲cookie是如何诞生的,因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。于是有这么一个人,网景公司的前雇员卢·蒙特利在1993年3月的发明了cookie。最初在1997年2月定义于 RFC 2109,后来有两次更新,于2000年10月的RFC2965和2011年4月RFC6265。
你可以发现这几个文档的标题都是: HTTP State Management Mechanism (http 状态管理机制) 。
讲到这里,有没有觉得cookie 是一个神奇的存在, 1993年发明的,一直用到现在 ,虽然互联网技术日新月异,但它还是保留下来,并且不可或缺,rfc文档 也有两次更新 。
到底是什么?
Cookie 是服务器保存在浏览器的一小段文本信息。这是个纯文本的信息,并且按照协议规定的格式来存储 。浏览器每次向服务器发出请求,就会自动附上这段信息,于是Web 服务器就可以使用这些信息来识别不同的用户 。生活中我们使用的大部分需要登录的网站,登录成功后都会设置一个cookie到浏览器,只要这个cookie 存在,用户就可以浏览网站的任意页面,手动清理掉这个cookie,就相当于退出登录。 这也就是为什么前言中会出现:如果禁用浏览器cookie功能,大部分网站就无法登录,无法使用需要登录后才能使用的功能了。
使用场景
会话(session)管理:保存登录、购物车等需要记录的信息。
个性化:保存用户的偏好,比如网页的字体大小、背景色、地域等等。
追踪:记录和分析用户行为,广告。
这里有必要提一下,浏览器对单个cookie的大小,一个网站的cookie个数,总的大小和个数都有限制,其实cookie不适合用来作为大量数据的客户端存储,如过需要这个功能,可以使用浏览器的Local Storage 、IndexDB等新的功能来替代,这里就不做延展。
cookie的缺陷
Cookie会被附加在每个HTTP请求中,所以无形中增加了流量。
由于在HTTP请求中的Cookie是明文传递的,所以安全性成问题,除非用HTTPS。
Cookie的大小限制在4KB左右,数量在20左右,对于复杂的存储需求来说是不够用的。
如何使用cookie
Cookie实际上是由浏览器在管理(浏览器放出接口),这个问题就变成如何指挥浏览器增删改查cookie ,我们知道浏览器是遵守http协议的,还有另一方web服务端也是遵守的。我们可以通过这个来指挥浏览器操作cookie。
Cookie 和http协议 (服务端操作cookie)
服务端要操作cookie是通过响应头:Set-Cookie , 浏览器接受到这个响应头 ,就相当于收到命令去操作cookie ,具体是添加cookie ,删除cookie 还是修改cookie 要看后面的值 ,一个Set-Cookie 响应头自能操作一个cookie ,一个响应可以有多个Set-Cookie响应头 ,这样一次响应就能操作多个cookie,
响应头中的cookie实例: Set-Cookie:ykjjdc=c89e252fb3ce3cf203f; domain=.jjw.com; expires=Mon, 21-Mar-2118 07:00:11 GMT; path=/
用 “;” 分隔的字符串,每一段基本是一个键值对。
服务端要获取cookie 是通过 请求头: Cookie ,http协议规定浏览器每次发起一个请求,要筛选符合要求的cookie(比如域相同,路径相同,没过期等)放在请求头Cookie中 传递给服务端 。
请求头中的Cookie实例: Cookie: cna=UfdnD69NHXgE8g; UM_distinctid=16223df34200
可以到也是用 “;” 分隔的字符串, 没一段就是一个cookie ,忽略了cookie的其他属性,也就是说服务端不知道这个cookie是谁写的,什么时候将会过期。
Cookie 和 javascript (客户端操作cookie)
document.cookie
是客户端读写cookie的唯一接口 ,这个属性可读可写 。
读的情况下,返回当前脚本路径下所有的cookie(不包含属性包好httponly的),按照相关性排序(解决不同路径下相同名字cookie的问题)。读出来的示例: iddc=fsfea; fsf=3; yssskjjdc=ssfe; ykjjdc=fsa
。
写的情况下,一次只能写一个cookie,不会覆盖已有cookie ,根据你写的内容,会出现 添加一个cookie ,修改一个cookie ,删除一个cookie等不同的结果 。
写的示例如下:
可以看出都是对字符串的处理,这种处理容易出错,目前比较流行的cookie帮助类有 jquery.cookie.js 和yui中的对cookie的相关函数。可以方便的读写cookie。
Cookie 和 Asp.Net 中的 System.Web.HttpCookie
不同服务端代码中对cookie封装的原理就是 基于 http协议中的cookie机制 ,上文中有提到,asp.net 也不例外。
asp.net 中有一个类 System.Web.HttpCookie 来对应cookie ,我们来看看他的结构
HttpCookie 属性 | cookie 原生属性 | 描述 |
Domain | domain | 获取或设置要将与 cookie 相关联的域。 |
Expires | expires | 获取或设置的过期日期和时间的 cookie。 |
HasKeys | 无 | 获取一个值,该值指示 cookie 是否有子项。subcookies应用 |
HttpOnly | httponly | 获取或设置一个值,指定 cookie 是由客户端脚本访问。 |
Name | name | 获取或设置 cookie 的名称。 |
Path | path | 获取或设置要与当前 cookie 传输的虚拟路径。 |
Secure | secure | 获取或设置一个值,该值指示是否传输,即通过 HTTPS 仅使用安全套接字层 (SSL)-的 cookie。 |
Value | value | 获取或设置一个单独的 cookie 值。 |
Values | 无 | 获取包含在一个 cookie 对象内的键/值对的集合。subcookies,解决cookie个数过多问题 |
无 | max-age | 对 expires属性的补充 ,存在浏览器兼容性问题 |
无 | host-only | 强制域完全一致才可访问 |
通过上表我们可以看到 ,原生cookie的属性基本和aspnet 中的一致。
我们可以通过Request.Cookies
得到请求头中的cookie ,并且可以很方便的拿到对应的值 ,
(有兴趣的朋友可以研究下 ,有相同的cookie名时服务端的取值情况 )。
在aspnet 中服务端可以通过下面的对象或者语法方便的操作cookie 。
但是笔者认为这个设计还不如 JavaScript中 cookie 的操作设计,一个属性增删改查全是它 。
这样的封装设计干扰了程序员对cookie的学习了解。
web.config 关于cookie的全局配置节点 , 你可以指定cookie的域 ,当然这个域必须和地址栏中的主域一致; 也可以为了安全起见配置httpOnlyCookies 使默认输出的cookie 都是js不能读取操作的 ; 还可以配置 requireSSL 是浏览器只有在https地址上发送这个cookie (这个的前提也是当前协议是用的https)。
HttpWebRequest 和 Cookie
工作中,除了浏览器发起http请求外, 还有一种情况是自己编写代码来发起http请求,比如对第三方http接口的请求。
Cookie 的应用
Cookie最核心的应用应该就是作为会话机制了,正如前言中提到的,浏览器停掉cookie ,大部分网站都无法登录的数据。 其实 asp.net 中的 Session[“”] 默认配置下,就依赖于cookie ,会在客户端用cookie存储一个sessionid 。
Cookie最常见的应用还有 ,记录用户的使用偏好 ,比如用户 常用城市, 语言 ,网站主题,字体等 , 当然这些都可以存储服务端和用户信息关联 ,但是如果网站不需要登录,这些数据存储在服务端就不合适了。
还有吗?
工具
浏览器本身就会提供cookie 的开关配置,用户可以根据自己需要来开启或者关闭,或者开启部分网站,关闭部分网站等设置 。
浏览器也会提供cookie的管理工具 , 但是大都不是很好用 。 chrome 内核浏览器 的开发人员工具可以很方便的查看cookie 但是管理就不是很便利了 。
浏览器插件是解决这个问题的终极方案, EditThisCookie 这款浏览器插件是个不错的选择。
Q&A
- 如果你需要写一个浏览器,你需要对cookie 做哪些处理
- 接口化开发,对于接口的响应中的cookie如何处理 。
- 除了通过 set-Cookie ,JavaScript 操作cookie ,还有其他方式吗
- 向图片,css ,js 发出的请求 会携带cookie 吗
- 说说cookie 的缺点
- 对我们工作的启发 ?
Thanks
资料
- https://zh.wikipedia.org/wiki/Cookie
- http://bubkoo.com/2014/04/21/http-cookies-explained/
- http://javascript.ruanyifeng.com/bom/cookie.html
- https://www.cnblogs.com/fish-li/archive/2011/07/03/2096903.html
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
- https://imququ.com/post/host-only-cookie.html
转载请遵循此协议:署名 - 非商业用途 - 保持一致
并保留此链接:http://fejerry.cnblogs.com/