作者:Gakki
- 要讨论 Token、Session 与 Cookie 的区别,我们先来简单的说一下 HTTP 协议。
- 什么是 HTTP 协议?
- HTTP 协议是 Hyper Text Transfer Protocol(超文本传输协议)的缩写。是用于万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的协议。
- 主要特点
- 简单快速:客户向服务器发送请求服务时,只需传送请求方法和路径。请求方法常用的有:GET、POST、DELETE等。由于 HTTP 协议简单,所以 HTTP 服务器的程序规模小,因此通信速度很快。
- 灵活:HTTP 协议允许传输任意类型的数据对象。传输的类型由 Content-Type 加以标记。
- 无连接:限制每次连接只处理一个请求。服务器处理完请求,并收到客户的应答后,即断开连接,采用这种方式可以节省传输时间。但是却不利于客户端与服务器保持会话连接。
- 无状态:是指协议对于事物处理没有记忆能力。无状态意味着如果后续处理需要前面的信息,它必须重新传递,这样就可能导致每次连接传递的数据量增大。另一方面,在服务器不需要先前信息时,它的应答就比较快速。为了弥补这个缺点,产生了两个 HTTP 状态的技术。即:Cookie 与 Session 。
- 支持 B/S 及 C/S 模式
1. Cookie 与 Session
1.1 什么是 Cookie
我们了解了 HTTP 协议之后,发现 HTTP 协议是无状态协议。为了弥补这一缺点,产生了 Cookie 与 Session 。
HTTP 协议中的 Cookie 包括
web cookie
和浏览器cookie
。Cookie存储在客户端
,它是服务器发送到Web浏览器并保存在本地的一小块数据。服务器将Cookie发送给浏览器,浏览器会进行存储,并与下一个请求一起发送到服务器。通常,它是用来判断两个请求是否来自于同一个浏览器
。比如:用户保持登录状态。Cookie 是不可跨域的
,每个 Cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠的是 Domain,Domain 指定 Cookie 所属域名,默认是当前域名)。-
Cookie 主要用于三个方面:
- 会话状态管理(如:登陆、购物车、游戏得分或者其他需要记住的信息)
- 个性化设置(如:用户偏好、主题或者其他设置)
- 浏览器行为追踪(如:记录和分析用户行为等)
-
Cookie 长什么样
- 简单的 Cookie :
Set-Cookie: <cookie名>=<cookie值>
- 简单的 Cookie :
-
Cookie 的分类
- 会话期 Cookie ::浏览器关闭之后它会被自动删除,仅在会话期内有效。会话期 Cookie 不需要指定过期时间(Expires)或者有效期(Max-Age)
- 持久性 Cookie : 和关闭浏览器便失效的会话期 Cookie 不同,持久性 Cookie 可以指定一个特定的过期时间(Expires)或有效期(Max-Age)。如:
Set-Cookie: uid=666; Expires=Wed, 1 Jun 2021 14:00:00 GMT
注:当 Cookie 设置了过期时间的时候,这个过期的清除操作是浏览器客户端操作,与服务器无关
1.2 Cookie 是怎样生成的
- 客户端会发送一个 HTTP 请求到服务器
- 服务器接收客户端发来的请求后,返回一个响应头( HTTP Response )给客户端,并且在响应头中设置 Set-Cookie 的字段
- 客户端保存 Cookie,之后客户端再向服务器发送请求时,HTTP Request 请求中会包含一个 Cookie 的头部
- 服务器接收请求,分解 Cookie,验证信息,核对成功后返回 HTTP Response 响应给客户端
- 以用户将商品加入购物车为例
- 用户每次将商品加入购物车的时候,客户端请求服务器,服务器都会将本次商品的 id 存储在 Cookie 中返回给客户端,客户端则会将 Cookie 保存到本地,下次再请求服务器的时候,再将上次保存在本地的 Cookie 传给服务器就行了。
- 仔细观察我们可以看出,随着购物车内商品数量的增多,服务器每次请求传的 Cookie 也会越来越大,这对之后服务器发送的每个请求来说负担都是很大的。
1.3 什么是 Session
- Session 是另一种记录服务器和客户端会话状态的机制
- Session 是基于 Cookie 实现的,Session 存储在
服务器端
,SessionId 会被存储到客户端的 Cookie 中
1.4 Session 是怎样生成的
- 用户第一次请求服务器的时候,服务器会根据用户提交的信息,创建相应的 Session ,返回响应的时候将 Session 的唯一标识信息 SessionId 返回给浏览器
- 浏览器接收到服务器返回的 SessionId 信息后,会将此信息存储到 Cookie 中,同时,记录 SessionId 属于哪一个域名
- 当用户再次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果有会自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionId ,再根据SessionId 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效。如果找到 Session,证明用户已经登录可以执行后面的操作。
注:根据流程,我们可以看出Cookie 与 Session 的关联性,即:SessionID 是连接 Cookie 和 Session 的一道桥梁
-
对比刚才的用户将商品加入到购物车案例
- 客户端将用户账号+密码发送给服务器,服务器会生成一个 Session ,为其分配唯一的SessionId
- 之后用户每次添加商品到购物车,客户端都会在 Cookie 里带上 SessionId 键值对,服务器根据收到的 SessionId 找到它对应的用户,并将商品 id 保存到服务器中对应用户的购物车里
1.5 Cookie 与 Session 的相同与不同之处
-
不同之处:
- 作用范围不同:Cookie 保存在客户端(浏览器),Session 保存在服务器,但当访问增多的时候,Session 会比较占用服务器的性能。
- 存取方式不同:Cookie 只能保存 ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等
- 有效期不同:Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
- 隐私策略不同:Cookie 存储到客户端,比较容易遭到不法获取;Session 存储到服务器,安全性相对 Cookie 要好一些,所以可以将登录等重要信息放在 Session ,其他信息如果要保留可以放在 Cookie 中
- 存储大小不同:单个 Cookie 保存的数据不能超过 4K ,Session 可存储数据远高于 Cookie
相同之处:Cookie 和 Session 都是用来跟踪浏览器用户身份的会话方式。
1.6 浏览器禁止 Cookie
- 如果浏览器中禁止 Cookie 怎么办了。
- 每次请求中都携带一个 SessionId 参数,可以以 Post 的方式请求,也可以在请求的地址后面拼接:
xxx?SessionId=985641
- 使用 Token(下面会详细讲解)
- 每次请求中都携带一个 SessionId 参数,可以以 Post 的方式请求,也可以在请求的地址后面拼接:
2. Token
2.1 什么是 Token 以及是怎样生成的
- Token 也称为 “令牌”,是服务端生成的一串字符串,以作客户端进行请求的一个令牌。一般由:由 uid + time + sign + [固定参数] 组成
- Token 的生成过程
- 客户端使用用户名+密码请求登录
- 服务端收到请求,去验证用户名+密码,验证成功之后,服务端会生成一个 Token ,并将 Token 发送给客户端
- 客户端接收到 Token 以后会将它保存到本地,之后客户端再次向服务端请求的时候,就将 Token 带上
- 服务端接收到请求,然后去验证 Token , 如果不存在 Token 、Token 错误或者 Token 过期,则拒绝请求;如果验证成功,就返回请求的数据
- Token 可以有效减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮
2.2 Token 的优势
- 支持跨域访问:Cookie 是不允许垮域访问的,Token 支持
- 无状态:Token 无状态,Session 有状态的
- 更适用于移动应用:Cookie 不支持手机端访问的
- 去耦:不需要绑定到一个特定的身份验证方案。Token 可以在任何地方生成,只要在你的 API 被调用的时候, 你可以进行 Token 生成调用即可
2.3 Token 与 Session 的区别
- Token 是服务器经过计算发给客户端的,服务器不需要保存,每次客户端发来请求,经过解密等计算来验证 Token 是否正确
- Session 是保存在服务器本地的,客户端每次访问服务器都会将 Session 发送给服务器,服务器接收到之后会在数据库中查找对应的 Session
- Token 值不需要占用内存,Session 值是需要存在服务端(不进行存储无法校验)
- Token 是可以跨平台(比如在电脑端取到 Token 值拿到手机登陆是可以使用)
- Session 不可以跨平台,因为 Session 生成的Cookie 是和域名 IP 绑定在一起,换个平台就失效了
杂谈
- 只要关闭浏览器 ,Session 就消失了?
- 错误!对 Session 来说,除非程序通知服务器删除某个 Session ,否则服务器会一直保存。程序一般都是在用户做 LOG OFF 的时候发送指令去删除 Session 。
然而浏览器从来不会主动在关闭之前通知服务器它将要关闭了,请将某个 Session 删除。因为服务器没有机会知道浏览器已经关闭了。之所以会有这种错觉,是大部分 Session 机制都使用会话 Cookie 来保存 SessionId ,而关闭浏览器后这个 SessionId 就消失了,再次连接服务器时也就无法找到原来的 Session 。如果服务器设置的 Cookie 被保存在硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的 SessionId 发送给服务器,则再次打开浏览器仍然能够打开原来的 Session。
恰恰是由于关闭浏览器不会导致 Session 被删除,迫使服务器为 Session 设置了一个失效时间,当距离客户端上一次使用 Session 的时间超过这个失效时间时,服务器就可以以为客户端已经停止了活动,才会把 Session 删除以节省存储空间。
- 错误!对 Session 来说,除非程序通知服务器删除某个 Session ,否则服务器会一直保存。程序一般都是在用户做 LOG OFF 的时候发送指令去删除 Session 。