1. Cookie
概述
Cookie是服务端保存在客户端的一小段文本
当未给Cookie设置过期时间时,该Cookie在当前会话结束时就会消失,这种Cookie称为Session Cookie,不保存在硬盘中而是保存在内存中
当设置了过期时间,该Cookie会保存在硬盘中,只要没有过期,即使浏览器窗口被关闭,该Cookie也不会消失
每个浏览器有各自的Cookie,这意味着用不同的浏览器访问同一个网站,生成的Cookie都是不同的,互相不影响
每个网站都有各自的Cookie,保存在本地,并且互相不影响
每个Cookie的大小一般不超过4KB,浏览器每次向服务器发出请求,就会自动附上这段信息
Cookie可以由服务端写入,也可以由客户端写入
那么问题来了,Cookie中会存放着哪些数据呢?
比如说登陆状态,自定义设置,选中的添加到购物车中的商品,下面会具体说一下其中原理
登陆状态
当我们通过登陆界面登陆成功后进入到下一个页面后,下一个页面是如何知道我们的登陆状态呢,并且享有怎样的权力呢(比如说是否是VIP用户)
输入帐号和密码点击登陆发送一个请求到服务端,服务端在数据库中检测帐号和密码正确后,就会在客户端的Cookie中写入登陆状态为成功(猜测是一个加密过的状态码,在服务端生成加密码然后写入到该用户的相应的数据库中,然后再在Cookie中写入该状态码,只要在下一次请求中,Cookie中的状态码与该用户数据库中的码对上了就可以获得登录状态)
每个网站在客户端生成的Cookie是用户(浏览器)在这个网站中的唯一标识,Cookie中的一个ID值与该网站的数据库中的一个用户数据是一对一关系
Session是基于Cookie的,所以这个原理感觉有点类似
选中的添加到购物车中的商品
客户端发出添加到购物车这个请求到服务端时,服务端根据客户端请求中的商品编号,把这些商品编号写入到客户端的Cookie中,当发出进入购物车页面请求时,服务端会根据Cookie中的商品编号从数据库中选出对应的商品渲染到页面上,这就是Cookie的简单应用
自定义设置实现的原理也是类似的
以上都是自己猜测的,然后我更好奇服务端随机生成的状态码存储在Cookie中,万一被窃取了,是不是就可以窃取用户的登陆状态了,甚至于窃取更多数据
Cookie包含以下几方面的信息:
Cookie的名字
Cookie的值(真正的数据写在这里)
到期时间
所属域名(默认是当前域名)
生效的路径(默认是当前网址)
浏览器可以设置不接受Cookie,也可以设置不向服务器发送Cookie
window.navigator.cookieEnabled;//true
//浏览器是否打开Cookie功能
document.cookie;//该属性返回当前页面的Cookie
不同浏览器对Cookie数量和大小的限制是不一样的,一般来说,单个站点设置的Cookie不应超过20个,每个大小不能超过4KB,超过限制后,Cookie将被忽略,不会被设置
浏览器的同源政策规定,两个网址只要域名和端口相同,就可以共享Cookie,这意味着不同协议的两个网址可以共享Cookie
Cookie和HTTP协议
Cookie由HTTP协议生成,也主要是供HTTP协议使用
HTTP回应:Cookie的生成
服务器如果希望在客户端保存Cookie,就要在HTTP回应的头部信息中,像下面这样:
Set-Cookie:foo=bar
res.setHeaders('Set-Cookie','foo=bar');//猜测在Node中是这样的
HTTP回应可以包含多个Set-Cookie
字段,即在客户端生成多个Cookie
除了设置Cookie的键和值,Set-Cookie
还可以附加Cookie的属性(后文解释)
如果服务器想改变一个早先设置的Cookie,必须同时满足四个条件:
Cookie的key,domain,path,secure都匹配,否则将会生成一个全新的Cookie
HTTP请求:Cookie的发送
浏览器向服务器发送HTTP请求时,每个请求都会带上相应的Cookie
好像是HTTP设置的,每次HTTP请求,都会自动带上相应的Cookie
服务器收到客户端发送过来的Cookie时,有两点是无法知道的
Cookie的各种属性,比如说何时过期
哪个域名设置的Cookie
Cookie的属性
Expires,Max-Age
Expires
属性指定一个具体的到期时间,到了指定时间以后,浏览器就不再保留这个Cookie了
它的值是UTC格式,可以使用Date.prototype.toUTCString
进行格式转换
如果不设置该属性,或者设置为null
,Cookie只在当前会话有效,浏览器窗口一旦关闭,当前Session结束,该Cooike就会被删除
另外,浏览器根据本地时间,决定Cookie是否过器,由于本地时间是不精确的,所以没有办法保证Cookie一定会在服务器指定的时间过期
Max-Age
属性指定从现在开始Cookie存在的秒数,比如说60*60*24*365
(即一年),过了这个时间后,该Cookie才有可能会被删除
如果同时指定了
Expires
和Max-Age
这两个属性,那么Max-Age
的值优先生效
如果Set-Cookie
字段没有指定Expires
或Max-Age
属性,那么该Cookie就是Session Cookie,即它只在本次会话中存在,一旦用户关闭浏览器,浏览器就不再保留该Cookie
Domain,Path
Domain
属性指定浏览器发出HTTP请求时,哪些域名要附带这个Cookie
如果没有指定该属性,浏览器会默认将其设为当前URL的一级域名
如果该属性设置的域名不属于当前域名,浏览器会拒绝这个Cookie
Path
属性指定浏览器发出HTTP请求时,哪些路径要附带这个Cookie
只要浏览器发现,Path
属性是HTTP请求路径的开头一部分,就会在头信息中附带上这个Cookie
Secure,HttpOnly
Secure
属性指定浏览器只有在加密协议HTTPS下,才能将这个Cookie发送到服务器
另一方面,如果当前协议是HTTP协议,浏览器会自动忽略服务器发来的Secure
属性,该属性只是一个开关,不需要指定值,如果通信是HTTPS协议,该开关自动打开
该属性好像没啥用
HttpOnly
属性指定该Cookie无法通过JavaScript脚本拿到,主要是防止document.cookie
属性拿到该Cookie并发给第三方服务器造成信息泄漏
同时,XMLHttpRequest
对象和Request API
都拿不到该属性,这样就防止该Cookie被脚本读到,只有浏览器发出HTTP请求时,才会自动带上该Cookie
document.cookie
该属性用于读写当前页面的Cookie
读取时,它会返回当前页面的所有Cookie,前提是该Cookie不能设置HTTPOnly属性
写入时,Cookie的值必须写成键值对的形式,同时该方法一次只能写入一个Cookie,而且写入并不是覆盖,而是添加,即为当前网站添加Cookie
写入时,还可以一起写入Cookie的属性
document.cookie = "foo=bar; expires=Fri, 31 Dec 2020 23:59:59 GMT";
Cookie属性一旦设置完成,就没有办法读取到这些属性的值
删除一个现存Cookie的唯一方法,是设置它的expires属性为一个过去的日期
document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';
//删除了一个名为fontSize的Cookie
2. Web Storage
Web Storage与Cookie的区别
Web Storage的概念与Cookie相似,区别是它是为了更大容量存储设计的,基本上都是5M存储
Cookie的大小是受限的,并且每次请求一个新页面时都会将其发送给服务端,无形中浪费了带宽,另外Cookie还需要指定作用域,不可跨域调用
除此之外,Web Storage有一套成熟的API,比起操作Cookie方便的多
但是Cookie也是不可或缺的,Cookie作用是与服务端进行交互,作为HTTP规范的一部分存在,而Web Storage仅仅是为了本地存储数据存在的,不会自动把数据发送给服务端
Web Storage分类
session Storage
其引入了一个‘’浏览器窗口’‘,session Storage是在同源的同窗口中始终存在的数据,也就是说这个浏览器窗口没有关闭,即使刷新页面或进入同源的另外一个页面,数据仍然存在,一旦关闭窗口,session Storage就会被销毁,同时独立打开的不同的窗口,即使是同一个页面,session Storage对象也是不同的
猜测session Storage是存储在浏览器内存中
local Storage
存储的数据是永久保存,保存在硬盘中,即使关闭浏览器窗口或关闭浏览器,该数据也不会丢失,在不同窗口也会共享数据,只要是同源的网站就可以共享local Storage
Web Storage API
增,改
window.localStorage.setItem(key,value)
删
window.localStorage.removeItem(key);//按照键名删除
window.localStorage.clear();//删除全部
查
window.localStorage.getItem(key);
3. session(服务端)
session是基于cookie实现的
session与cookie的区别
前者真正的数据是存储在服务端的,后者数据是存储在客户端的,因此前者比后者安全
但是前者会增加服务端的负担,后者可以减轻服务端的负担
建议将重要信息保存在前者中(比如说登陆信息,身份信息),其它信息(购物车,自定义设置)保存在后者中
前者保存在服务端,客户端不知道其中信息,后者保存在客户端,服务端可以知道其中信息
Node中的session
当服务端需要为某个请求创建一个session时,首先会检查该请求中是否已包含一个session id,如果已包含说明以前已经为此客户创建过session,服务端就会按照该session id检索session对象(真正的数据存储在此对象中),如果检索不到,就会新建一个;如果客户端的请求中不包含session id,就会新建一个session对象并生成一个与该session对象绑定的session id(该id的值应该是一个不会重复又不会容易被找到规律以仿造的字符串),该session id将在本次响应中返回给客户端保存(保存方式可以采用Cookie)