Cookies和session是什么?有什么用处?
先来说说cookie。
第一cookie是干什么的? 换句话说,cookie为什么有存在的必要?
首先,早期的服务器面临一个问题,就是如何分辨两个请求时同一个浏览器做出的。服务器只会对请求做出响应,而无法分辨这一点,这就会带来一些问题,比如服务器如何知道这个请求是否来自于一个已经登陆的浏览器,而选择做出何种响应。
所以得出一个结论,浏览器和服务器之间需要一种存储状态的数据。
cookie就是用来做这件事的。
cookie本质:
cookie本质上是一(小)段文本,就像它名字的含义——曲奇,小小的,味道不错。
工作方式 :
需要的时候,当浏览器存在cookie时,每当浏览器向服务器发送数据,都会将cookie存放在HTTP头中,一起发送到服务器。而在服务器和浏览器中,都可以操作cookie。
需要做出的要求:
创造cookie,我们就需要考虑到它的一些要求,比如cookie的大小限制,数量限制,增删改,作用范围,有效时间等等,这就有一些我们需要确定的规则,下面来具体说说。
cookie的创建,修改,删除
不管在何种技术(js,或js框架等等)中创建cookie,都需要在创建的同时提供一个配置参数,用来指定创建的cookie的具体配置要求,主要有以下这些:
expires
: 过期时间,如果不设置的话,就是会话级别的,即当浏览器关闭后会删除domain
: 域名 (浏览器将该参数和请求的域名从后往前比较。比如domain设置为.github.com
可以访问my.github.com
和some.github.com
)path
: 路径 (从前往后比较,如/host
可以访问/hostabc
)secure
: 安全选项,(不用指定值)设置时只有请求通过SSL或HTTPS创建时,该cookie才会发送至服务器httpOnly
: (不用指定值)设置时,cookie就不能通过JavaScript的document.cookie
访问。是在IE6时加入的选项,现代的浏览器大都支持该属性(3.2 版本的 Safari 仍不支持)。如果设置该属性,IE进一步不允许通过XMLHttpRequest
的过去HTTP响应头的方法获得cookie,火狐在 3.0.6 修复了该漏洞,但是有的浏览器仍存在该漏洞。
cookie数量和大小限制
很明显,cookie只是存储状态的,不应该被滥用,(毕竟每次请求和响应都会传送cookie)所以cookie的数量是有限制的,这在不同的浏览器中有不同的情况:
- 在IE7之前(不包括IE7),每个域名下的cookie数量限制为20个,IE7及以后,每个域名下的cookie数量限制为50个。
- Firefox每个域名的cookie数量限制为50个。
- Opera每个域名的cookie数量限制为30个。
- Safari/WebKit没有数量限制,但是当cookie的数量非常多时,HTTP头部的大小可能会超过服务器所能承受的范围。
另外一个问题,就是当cookie数量超出限制的时候,浏览器会如何处理?有两种途径:
- 大多数的浏览器,当cookie数量超过限制时,会将最早设置的cookie“踢”走,然后放进新设置的cookie。
- 而Firefox却不一样,它会随机的删除已存在cookie,所以对于这种情况,我们就应该不去超过cookie的数量限制,避免出现不可控的错误。
一个domain下所有的cookie的大小总和也是有限制的,在各个浏览器中都是4K字节(+-1字节),超出大小限制的部分会被忽略。
note:关于cookie的限制,参考了Nicholas C. Zakas的文章,原文链接。
subcookie
这是一种被用来处理cookie的数量限制的手段,就是在一个cookie中设置多个键值对,例如:
name=a=b&c=d&e=f&g=h
当然,这样设置就要求我们自定义从cookie中获取真正需要的数据的方法,当然,也有些服务器框架提供了这些方法。
然后我们再来说说session
session,顾名思义,它是一种保持会话状态的工具。
先来思考一下,cookie有哪些特点(在某些情况下成为缺点)?
有一个非常重要的特点,就是cookie在客户端和服务器都可以访问(虽然提供了httpOnly方式,但还不能很好的避免这一点)。而有些场景下,我们需要的是一种在客户端不能够访问的类似于cookie的东西,一种典型的情况就是用户登陆会话:
用户的登陆状态应该被保存下来,在客户端和服务器之间通信(这样服务器才能知道发过来的请求的登陆状态)。并且这个信息在客户端应该是无法访问的,不然就可以窃取或者伪造一个一样的信息发送给服务器,而得到本来不应该得到的响应。
所以session就是挺身而出来完成这个任务的。
###session的工作方式
session是基于cooike建立的,其原理大概是:
设置一个session
,包含一系列配置属性(和cookie类似,大概就是过期时间,安全这些属性的配置。)指定这个session的配置信息,这样一个session就设置好了。
然后我们就可以在这个session
中设置各种各样的键值对,这些信息就只能由服务器增删改查,并且存储在服务器的内存或数据库中。
而session
在服务器与客户端之间的传输,则是借助cookie
来完成的。web框架一般都会提供session的API,可以为一个session生成一个独一无二的ID,这个ID本身没有任何含义,就是一段挺长的乱码,这段乱码存储在一个cookie中,在服务端和客户端之间用来对口令(确定是同一个session)。这样的话,客户端看到的就只是一段乱码,不能获取任何有效信息,如果改动的话,自然也就不能匹配服务器端的session了。
session的安全问题
虽然不能获取有效信息,也不能改动,但是如果是HTTP协议的传输(一种明文传输),那么还是有可能劫持下这个ID,然后加入到自己的请求中,匹配到服务器端的session了。解决这个的方法是动态刷新session,加上token等,但是也不能完全避免问题,所以这时候也许就需要HTTPS了。
关于session的理解,参考了这篇文章。 ***
最后简单讲一下cookie和session的使用:
在各种与web客户端和服务端相关的技术中,如果有必要的话,都会提供操作cookie或session的API,比如我正在使用的JavaScript中的document.cookie
和Koa中的ctx.cookies.set
和ctx.cookies.get
,ctx.session
等。当然,这些方法都是对cookie的一个封装,但本质上来说都是一样的。