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等不同的结果 。 
写的示例如下:

document.cookie = "foo=bar; expires=Fri, 31 Dec 2020 23:59:59 GMT";

可以看出都是对字符串的处理,这种处理容易出错,目前比较流行的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 。

Response.AppendCookie()
Response.AppendHeader("Set-Cookie" ,"iron=fage");
Response.SetCookie()
Response.Cookie.Add()

但是笔者认为这个设计还不如 JavaScript中 cookie 的操作设计,一个属性增删改查全是它 。 
这样的封装设计干扰了程序员对cookie的学习了解。

web.config 关于cookie的全局配置节点 , 你可以指定cookie的域 ,当然这个域必须和地址栏中的主域一致; 也可以为了安全起见配置httpOnlyCookies 使默认输出的cookie 都是js不能读取操作的 ; 还可以配置 requireSSL 是浏览器只有在https地址上发送这个cookie (这个的前提也是当前协议是用的https)。

<httpCookies domain="String"
httpOnlyCookies="true|false"
requireSSL="true|false" />

HttpWebRequest 和 Cookie

工作中,除了浏览器发起http请求外, 还有一种情况是自己编写代码来发起http请求,比如对第三方http接口的请求。

CookieContainer cookieContainer = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.CookieContainer = cookieContainer;//这个属性用来传递cookie
 
using( WebResponse response = request.GetResponse() ) {
using( StreamReader reader = new StreamReader(response.GetResponseStream(), encoding) ) {
return reader.ReadToEnd();
}
}
//执行上面的代码后,如果http响应中有cookie,将会追加到 cookieContainer ;

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

资料

Cookie 没你不行的更多相关文章

  1. session & cookie(li)

    Session & Cookie 一.定义 Session,用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间.Cookie,由服务器端生成,发送 ...

  2. 进阶——scrapy登录豆瓣解决cookie传递问题并爬取用户参加过的同城活动©seven_clear

    最近在用scrapy重写以前的爬虫,由于豆瓣的某些信息要登录后才有权限查看,故要实现登录功能.豆瓣登录偶尔需要输入验证码,这个在以前写的爬虫里解决了验证码的问题,所以只要搞清楚scrapy怎么提交表单 ...

  3. Cookie中图片的浏览记录与cookie读取servle时路径的设置(文字描述)

    public class ShowServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpSer ...

  4. vue.js设置、获取、删除cookie

    项目需要前端获取后台返回的cookie,并以此作判断.我是在main.js入口文件下使用的 具体代码: new Vue({ el: '#app', router, template: '<App ...

  5. 向后台提交数据:利用cookie加session提交更多数据,

    个人逻辑,可能考虑不全面,各位看到后留言,我修改啊 实现效果:浏览器第一次访问提交用户名,后台验证通过,生成随机字符串,和用户名组成字典,保存到服务器,把随机字符串设置成cookie发给浏览器,同一个 ...

  6. 如何知道网页浏览器cookie是什么?

    一直有网友问网页cookie如何获取,其实想知道自己访问网页时的cookie没那么难,用Chrome内核浏览器的debug功能就能看到,怎么查看呢?随ytkah一起来看看吧! 打开网页,按F12键,选 ...

  7. [py]flask操作cookie&django的seesion和cookie机制

    浏览器同源策略(same-origin policy) csrf攻击防御核心点总结 django的cookie和session操作-7天免登录 flask操作cookie&django的see ...

  8. Cookie、Session 和 Token区别

    1 Cookie.Session 和 Token 都是用来做持久化处理的,目的就是让客户端和服务端相互认识.Http 请求默认是不持久的没有状态的,谁也不认识谁.   2 Cookie: 是存放在客户 ...

  9. Cookie技术

    u  常用的API 创建Cookie对象 Cookie(String name, String value)    ->以指定数据创建Cookie对象 设置Cookie对象 void setMa ...

随机推荐

  1. Http协议-概要

    Http协议(超文本传输协议)是位于TCP/IP结构中的应用层的一种传输协议,规定了万维网服务器之间相互通信的规则.比如比较常见的Web浏览器客户端与应用服务器的通信!万维网服务器之间互相通信的时候往 ...

  2. VMWare安装Ubuntu 16.04

    1.Ubuntu安装文件下载 到Ubuntu官网下载安装包,有Bit Torrent.Network installer多种方式下载. 推荐使用中国地区的镜像下载,我是用华科的校园网下载速度是非常感人 ...

  3. hostent结构体和wsadata结构体

    一.hostent结构体 使用这个东西,首先要包含2个头文件:#include <netdb.h>#include <sys/socket.h> struct hostent ...

  4. 异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource

    1 进程-线程-多线程,同步和异步2 异步使用和回调3 异步参数4 异步等待5 异步返回值 5 多线程的特点:不卡主线程.速度快.无序性7 thread:线程等待,回调,前台线程/后台线程, 8 th ...

  5. 过滤asp.net页面每次发出请求之前访问

    public class PageFiltert : System.Web.UI.Page { public PageFiltert() { // //TODO: 在此处添加构造函数逻辑 // } p ...

  6. 无监督学习:Deep Generative Mode(深度生成模型)

    一 前言 1.1 Creation 据说在费曼死后,人们在他生前的黑板上拍到如图画片,在左上角有道:What i cannot create ,I do not understand. Generat ...

  7. PHP json 对象 数组互相转换

    json格式转为数组/对象 json_decode() json 对象/数组转json格式 json_encode()

  8. 洛谷P1044 栈(Catalan数)

    P1044 栈 题目背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). 栈的重要 ...

  9. scrapy爬取数据的基本流程及url地址拼接

    说明:初学者,整理后方便能及时完善,冗余之处请多提建议,感谢!   了解内容: Scrapy :抓取数据的爬虫框架     异步与非阻塞的区别   异步:指的是整个过程,中间如果是非阻塞的,那就是异步 ...

  10. Swing 100行画图示例

    关键内容,可以自行扩展 package main; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt ...