引言
http是一个无状态协议
很久之前,Web基本上就是文档的浏览,服务器不需要进行什么记录。这一次请求和上一次请求没有任何关系,无状态带来的好处是快速。
如何保持Web浏览状态?
但是随着交互式Web应用,马上就面临了一个问题,例如在线购物等需要登陆的网站,服务器没办法单单从网络连接上知道访问者的身份。为了使某个域名下的所有网页能够共享某些数据,技术上推出了各种保持Web浏览状态的手段,例如session和cookie。
客户端记录、服务端记录
星巴克开始优惠活动,每消费10杯咖啡,会免费赠送1杯。所以需要采取某种方式来记录顾客的消费数量。
- 方式1:分给顾客一张卡片,每消费一次记录一次;(客户端记录 cookie)
- 方式2:发给顾客一张卡片,上面有卡号,顾客每消费一次,由店员在操作机上记录一次。(服务端记录 session)
cookie
什么是cookie?
小甜品,小饼干
在 Internet 中,cookie 实际上是指小量信息,是由服务器创建,将信息存储在用户计算机上的文件。cookie 在计算机中是个存储在浏览器目录中的文本文件,当浏览器运行时,存储在 RAM 中发挥作用 (此种 Cookies 称作 Session Cookies),一旦用户从该网站或服务器退出,cookie 可存储在用户本地的硬盘上 (此种 Cookies 称作 Persistent Cookies) 。
- 限制:客户端可禁用 cookie
cookie机制
- 首先,客户端会发送一个http请求到服务器端。
- 服务器端接受客户端请求后,发送一个http响应到客户端,这个响应头,其中就包含
Set-Cookie
头部。Set-Cookie: value[; expires=date][;domain=domain][;path=path][;secure]
- 在客户端在请求头中添加cookie发起第二次请求,提供给服务器端可以用来唯一标识客户端身份的信息。
- 服务器接收请求,分解cookie,验证信息核对成功后返回response给客户端。
cookie构成
服务器端向客户端发送cookie是通过HTTP响应报文实现的,在Set-Cookie中设置需要向客户端发送的cookie,cookie格式如下:
Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2019 11:29:42 GMT;HttpOnly;secure"
其中name=value
是必选项,其它都是可选项。
name
:cookie的名字,一旦创建,名称不可更改,不区分大小。value
:cookie的值,如果值为Unicode字符,需要为字符编码。如果为二进制数据,则需要使用BASE64编码.domain
: 域.可以访问该cookie的域名。第一个字符必须为".",如果设置为".google.com",则所有以"google.com结尾的域名都可以访问该cookie",如果不设置,则为所有域名.path
:表示这个cookie影响到的路径,浏览器跟会根据这项配置,像指定域中匹配的路径发送cookie。如果设置为"/sessionWeb/",则只有ContextPath为“/sessionWeb/”的程序可以访问该cookie。如果设置为“/”,则本域名下ContextPath都可以访问该cookie。expires
: 失效时间,表示cookie何时该被删除的时间戳。如不设置,浏览器会在页面关闭时删除所有cookie;如设置一个过去的时间,浏览器会立即删除该cookie;如果客户端和服务器端时间不一致,使用expires就会存在偏差。max-age
:cookie失效时间,单位秒。如果为正数,则该cookie在maxAge后失效。如果为负数,该cookie为临时cookie,关闭浏览器即失效, 浏览器也不会以任何形式保存该cookie。如果为0,表示删除该cookie。默认为-1,max-age的优先级高于expires。HttpOnly
: 告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置。secure
: 安全标志,指定后,只有在使用SSL链接时候才能发送到服务器,如果是http链接则不会传递该信息。
session
会话
什么是session?
session是一种记录客户状态的机制,不同的是cookie保存在客户端浏览器中,而session保存在服务器上。客户端浏览器访问服务器的时候,服务器使用一种类HashTable结构来保存信息。 客户端再次访问时只需要从该session中查找该客户的状态就可以了,避免了在客户端Cookie中存储敏感数据.
服务端session + 客户端sessionId
- 用户向服务器发送用户名和密码
- 服务器验证通过后,服务器自动创建session对象和唯一标识的sessionId,在当前对话(session)里面保存相关数据,比如用户角色,登陆时间等; 并向用户返回sessionId, 写入用户的cookie,如果用户禁用cookie,则要使用URL重写,可以通过
response.encodeURL(url)
进行实现 - 用户随后的每一次请求, 都会通过cookie, 将sessionId传回服务器
- 服务端收到sessionId, 按照sessionId把这个session检索出来使用,找到前期保存的数据, 由此得知用户的身份
缺点:
- 扩展性不好是最突出的问题
- session保存内容越多,越占用服务器内存,在线用户越多,服务器内存压力越大。
- CORS(跨域资源共享)
- CSRF(跨站请求伪造)
Token
令牌
服务端无状态的认证方案,服务端不会保存用户认证的数据
- 用户通过用户名和密码发送请求
- 程序验证
- 验证成功后,程序返回一个签名的token给客户端
- 客户端将token存放于localStorage等容器中, 并在每次请求中都通过headers携带token
- 服务端解密token(token字符串里保存了用户的所有信息)并返回数据
优势:
- 无状态、可扩展
- 安全,不再发送cookie,能防止CSRF
- 支持多平台跨域
Access-Control-Allow-Origin:*
- 基于标准,有现成的标准可用——JWT(JSON Web Token )
webStorage
Web Storage API提供机制, 使浏览器能以一种比使用Cookie更直观的方式存储键/值对,用于本地大容量存储数据,存储量大到5MB
localStorage 本地存储
- 永久性存储;存储到了电脑的硬盘和内存中;
- 当关闭页面或者是浏览器时,存储的内容不会消失;
localStorage.setItem("table",18);
localStorage.getItem("table");
localStorage.removeItem(key);
localStorage.clear(); // 清除所有key-value
sessionStorage 会话存储
- 只在当前页面中可以获取,在新标签或窗口打开一个页面时会初始化一个新的会话。
- 不能在页面之间进行通信;
- 会话存储,当关闭浏览器或页面时,存储自动消失;
sessionStorage.setItem(key,value);
sessionStorage.getItem(key);
sessionStorage.removeItem(key);
sessionStorage.clear();
小结
- cookie、session、token是用于客户端和服务端间的状态保持机制;
- web storage是用于本地大容量存储数据(web storage的存储量大到5MB)
session | cookie | |
---|---|---|
保存位置 | 服务器 | 浏览器 |
存储 | 以Hashtable的数据结构存储Object | 以文本方式存储String |
生命周期 | 随会话关闭结束(主要是cookie被清空的原因) | 一般由服务器生成,可指定有效期 expires ,如果在浏览器端生成,默认关闭浏览器后时效 |
数据大小 | 没有上限,考虑服务端性能,不要存放过多,并设置session删除机制 | 一个浏览器能创建的 cookie 数量最多为 300 个,每个不超过 4KB,每个 Web 站点能设置的 cookie 总数不能超过 20 个 |
跨域 | 不支持 | 支持,可通过domain 设置 |
安全性 | 要攻破session,先攻破cookie;启动session_start; sessionId是加密的。 比cookie安全,存放重要信息 | 对客户端可见,不安全,存放非重要信息 |
参考