Cookie机制详解
Cookie:一种web服务器和web客户端之间通信的机制。
在开始讲解之前,我先讲一下Cookie的产生理由:
Cookie产生的基本原因是因为HTTP是一种无状态的协议。
当一个客户端A请求一台服务器B,服务器B做出响应之后。客户端A和服务器B就互为陌生人了。当客户端A再次访问服务器B的时候,在没有做任何处理的情况下(处理手段如:URL重写,隐藏表单域,cookie,session),服务器B并不知道这个客户端A就是之前已经访问过的客户端。
PS:可能有人要问,为什么HTTP不设计成有状态的,这个的原因很多,你只要知道,现在的事实就是HTTP是一种无状态的协议。
随着时代的发展,如淘宝这样的电商网站如雨后春笋般出现在了网络上,而网站的请求都是经过HTTP请求的,如果在客户端每次请求之后,服务器都无法判断这个客户端是谁,那么想淘宝的会员体系就没法实现了。
所以,为了解决HTTP无状态的问题,人们提出了一种方式:利用Cookie技术。
Cookie机制的基本流程:
1. 客户端K 通过浏览器L 第一次访问 服务器F
2. 服务器F 在HTTP通过set-cookie头部设置了一个标志客户端K的字符串回送到 客户端K
3. 客户端K的浏览器L检测到响应头部有set-cookie这个HTTP头部后,将他的值存储在硬盘中。
4. 第一次请求完毕(在这个过程中,服务器在响应的时候,将一个标志客户端的字符串放在了HTTP头部中,当客户端浏览器收到HTTP报文,并检查其头部的时候,发现有set-cookie字段,于是把他的值存储在了客户端的硬盘中,请注意,在这个过程中,浏览器的作用很重要,是他自动把cookie存储在客户端硬盘的,也就是说,如果你的浏览器不具备,或者已经禁止了保存cookie这个功能,那么cookie这个机制就会失效了)
5. 客户端K再次通过浏览器L访问服务器F(在这个过程中,浏览器L接受到访问服务器F的命令后,它会先去它之前存储Cookie的地方看看有没有已经存储起来的cookie,如果有,那么就会将该cookie值放在HTTP的cookie头部中,作为请求头发送服务器F)
6. 服务器F接受到请求后,程序员编写的程序可以通过语言提供的方法(如:PHP的$_COOKIE)来访问到HTTP头部中的cookie字段值,根据都出来的值,服务器就可以判断该客户端K就是刚刚访问过的,因为cookie值就是在第二步中,服务器发送到客户端的。
7.再次访问结束。再次访问过程中cookie的值已经产生作用了,因为他的存在,服务器知道了客户端就是刚刚已经访问过的客户端。在这个过程中,有两点需要注意:一是浏览器会自己带上cookie发送给服务器,不用做任何其他动作。第二是服务器需要自己进行判断cookie来判断是否是刚刚访问的客户端。
阶段总结:所谓Cookie就是在HTTP头部上放置一些服务器生成的字符串,浏览器会在收到cookie的时候保存,和请求的HTTP的时候会自动带上cookie返回给服务器。在cookie机制中,浏览器是最重要的角色,没有它的自动保存和自动发送,cookie机制就无法起作用。
所以,学习cookie就是学习以下几个方面
1. 了解cookie在HTTP头部中的格式
2. 如何在服务器端读取设置cookie(和相应的后台语言有关,PHP,JAVA,C#)
3. 如何在客户端读取和设置cookie(只有一门JavaScript)
那么,开始真正的学习吧。
1. 了解cookie在HTTP头部中的格式
cookie在HTTP的请求头中和HTTP响应头中显示的头部字段是不同的,分别如下图:
这两张图是我从谷歌浏览器的网络面板截取的,可以看到:
1.在请求头中:
cookie是存放在Cookie字段中的,但是他为什么会自己出现在请求头中呢?我很确定,前端工程师并没有用JavaScript往请求头中加该字段值(因为是我写的)。
其实,该值是由浏览器帮我们加进去的,当我们在浏览器的地址输入栏中输入一个地址,并按下Enter键进行访问的时候,浏览器会自己根据我们输入的域名,跑去一个专门存储着cookie的文件里查找,看看再此次访问之前,有没有cookie是属于该网站,并且还没有过期的,如果找到就把cookie值取出来,并赋值给HTTP请求头的的Cookie字段,如果查到了多个cookie,则会以";"分割开。
在这个过程中,是不需要程序员写任何代码的,这是属于浏览器的工作(前提是浏览器没有被禁止使用Cookie的情况下)。
在请求头中,cookie的格式是很简单的:Cookie:key=value;key=value;
2.在响应头中
Set-Cookie:ECS=grid; expires=Sat, 07-Apr-2018 14:23:13 GMT; Max-Age=604800
当浏览器收到含有Set-Cookie字段的响应头时,他会将该cookie存储在一个cookie文件中,这个cookie文件其实就是硬盘上一个普通文件,而所谓cookie就是该文件中的一行字,是由浏览器进行维护的。
和请求头中字段cookie不同,在响应头中,用set-Cookie来表传递Cookie值,这个值是程序员使用服务器语言设置的,比如PHP的setcookie() 函数
setcookie其他诸如Java,C#等等,但凡能进行HTTP请求的语言都有相应的方式向HTTP响应头部中设置Cookie,并且,参数和上面的PHP是一样的,总共可以设置六个参数,下面分别讲解一下各个参数的含义:
1.name :Cookie的名字,也就是Key值,后台语言可以根据这个读取到cookie
2.value : Cookie的值,这个value和name是一个cookie的必须部分
3.expire :这个属性会指定一个日期字符串,用来说明该cookie的有效期,一旦过了该日期,浏览器在发送请求去cookie文件中查找时,就会忽略掉过期的cookie。日期的格式是定死的:Weekday, DD-Mon-YY HH:MM:SS GMT,日期唯一合法的时区GMT,如果在设置cookie的时候不设置expire字段,那么cookie会在会话结束之后立即过期。
4.domain:域名,标明该cookie是属于哪个域名下的,浏览器在发送请求去cookie文件中查找时,会根据请求的域名来搜索cookie文件,只提取出请求域名和domain的cookie,如domain值为office.com的cookie,在访问www.office.com和api.office.com时,浏览器都会带上该cookie返回给服务器,但是访问www.abc.com时就不会返回该cookie了,如果没有指定该值,则默认为请求头中的主机名。
5.path:提供了一个可以将同一个网站中不同模块的cookie隔离开的方法,比如domain:www.abc.com.而path:/foot/和path:/footer/,当访问www.abc.com/foot/index.html时,浏览器会不将path为/footer/的cookie返回服务器。如果没有设置该值,则默认为响应该HTTP请求的URL路径。
6.Secure:可选,如果在set-cookie中包含了该属性,则只有在HTTPS请求的时候才会带该cookie。
至此,关于cookie的知识基本上就清楚了,最后总结一下关于cookie的开发:
在前端
可以使用
document.cookie="username=John Doe; expires=Thu, 18 Dec 2019 12:00:00 GMT; path=/";设置cookie
使用 document.cookie获取cookie
在服务器端
如PHP。
通过$_COOKIE变量可以读取到请求头中的cookie值。
通过setcookie(name, value, expire, path, domain);可以将cookie设置到响应头中,浏览器会自行将cookie保存在客户端本地。
通过setcookie(name, value, expire, path, domain);将已存在的cookie的expire值设置为过去的时间,以让浏览器在客户端删除该cookie