Session、Cookie、Token、JWT分别都是什么?作用都有哪些?

Session、Cookie、Token、JWT分别都是什么?作用都有哪些? 目录一. 问题引入1.1 Web浏览器最初的作用1.2 交互网站的兴起与用户私有信息处理二. 最初的解决策略 Session2.1 Session 基本原理2.2 Session 的缺点2.3 问题的解决方案三. Token 详解3.1 Token 的组成部分3.2 Token 的原理3.3 Token 和 JWT 的关系四. Cookie 详解4.1 Cookie 是什么有什么用4.2 Cookie 的生成流程4.3 Cookie 常见属性4.4 Cookie 的安全性问题4.5 Cookie 的生命周期一. 问题引入1.1 Web浏览器最初的作用Web浏览器最初形成的时候主要是提供用户查阅文档浏览新闻。这些都是作为共享数据存储在服务器上的每一个用户都可以通过发送HTTP请求获取服务器资源。而且每次的 HTTP 请求都是一个新请求就是 请求响应 。服务器会将每一个 HTTP 请求都当成一个新的 HTTP 请求这也就是我们常说的 HTTP 请求是无状态的哪怕我上一秒刚请求过下一秒我再重新发送它还是会把我当成新的请求来处理不做记录不做区分只负责处理。1.2 交互网站的兴起与用户私有信息处理后来随着互联网技术的成熟Web 浏览器不再只是提供查阅功能开始出现各种各样的网上购物需要用户登录才能操作的功能和网站。此时我们就迫切需要一种技术将每个用户进行隔离虽然HTTP请求是无状态的但我们需要让每个用户发送过来的HTTP请求有状态换句话来说需要让服务器可以区分哪些HTTP请求是由用户A发送的哪些HTTP请求是由用户B发送的哪些HTTP请求是由用户C发送的可以对各自用户发送的HTTP请求进行区分。就这好比是打游戏我用自己的账号登陆游戏服务器游玩不可能说另一个人登陆游戏服务器玩的也是我的帐号吧或者说在浏览器淘宝店铺我买的商品下的订单不可能说另一个人进入之后也给他显示吧这些都属于是每个用户的私有数据不能像以前存储在服务器的共享文档数据一样公开。为了能够实现用户隔离由此就有了 SessionToken 等一系列网络技术。二. 最初的解决策略 Session2.1 Session 基本原理由于 HTTP 本身是么可有状态的我们也不能改变 HTTP。因此就有人提出可以使用标识Session翻译为会话服务器会分给客户端一个唯一的 Session ID其实是一个唯一的随机的字符串每个用户收到的 Session ID 都不相同然后服务器记录 Session ID。下一次客户端再发送 HTTP 请求过来就把标识 Session ID 也一并带过来这样一来服务器就可以区分出哪些 HTTP 都是由哪些用户发送的了然后就可以做出对应的数据处理。2.2 Session 的缺点上面说到了当用户来进行访问时生成一个 Session ID存储在服务器。那么随着用户量的逐渐增大服务器内部就会存储大量的 Session ID这无疑是巨大的资源开销会导致服务器水平扩展能力太弱此外大量的Session ID存储在服务器上如果哪一天服务器崩溃宕机了那么所有携带 Session ID 再次来进行访的用户都会被判断为Session 已失效或过期就需要用户重新进行权限校验或登陆操作这一点对用户体验是不太友好的。2.3 问题的解决方案解决方案一到这里我们更容易想的解决方案就是多设置几台服务器就算其中一台崩溃其他正常使用简单粗暴这样就能避免服务器崩溃带来的影响了。但与此同时也带来了另一个问题多台服务器的 Session 不共享如果服务器A生成了一个 Session将 Session 发送给用户的同时也需要将这个 Session 发送给其他几台服务器避免数据不同步导致用户下次访问时访问到其它服务器出现无此 Session 的情况。但是这样做也造成了很大的性能影响因为以生成一个 Session需要在多台服务器之间相互复制存储。解决方案二后来人们又想出了另一种对应策略将 Session 集中存储我们姑且称之为 Session 池然后让集群中的所有的服务器都去 Session 池中获取 Session 进行比对这样一来就避免了 Session 在多台服务器上重复复制的问题了并且服务器数量的增加也能提高并发时处理用户请求的效率。但这样一来也会有另一个问题如果存储 Session 池的服务器挂了怎么办有同学会说那我给 Session 池也设置一个集群就好了其实也可以但这样一来需要服务器的规模就太大了对于大的项目而言可以这样做但对于小的项目来说完全是资金的浪费。无论哪种方法我们可以看出一个共同的特点都是服务器存储机制。也就是说校验用户的信息资源存储在服务器端并没有存储在客户端。因此就有人提出为什么不让客户端存储呢由此就引出了我们要说的 Token。三. Token 详解Token 是有点类似于客户端存储机制。Session 则是服务端存储机制。3.1 Token 的组成部分Token 主要由 Header(头部)、Payload(载荷)、Signature(签名) 组成它们之间使用 . 分割共同构成一个完整的 Token 字符串。如下图所示、密钥本质上就是一个随机的 String 字符串在登陆系统中提前定义好就可以了。1Header 头部通常包含两部分Token的类型和所使用的算法。JWT就是下面我们要说的常用的Token类型之一算法有HMAC SHA256、RSA等2Payload 载荷就是主体部分主要存储以下三类用户数据用户信息如用户名、用户 ID 等。声明如过期时间、权限等。其他数据如用户的偏好设置、访问历史等。3Signature 签名是加密算法对Header Payload 密钥三者加密后生成的字符串。3.2 Token 的原理当用户进行登陆访问成功后服务器基于上面说到的某种加密算法(HMACSHA256RSA等) 进行加密生成签名(也有人说是令牌都可以)然后服务器将生成的签名(令牌)发送给用户以后用户在进行访问就带着签名(令牌)过来通常都存放在HTTP请求头。下一次用户再进行访问的时候服务器先获取请求头中的 Token然后使用和上述一样的方法再次重新生成签名然后与用户访问携带的 Token 中的签名进行比对。如果相等则说明当前用户已经登陆过了直接放行并根据 Token 中授予的权限进行授权。如果生成的 Token 与用户携带的 Token 不同则说明用户的信息被篡改过直接返回未授权禁止访问。这种方法安全系数还是比较高的很难破解即使知道了加密的方式但由于服务器密钥未知加密后的签名也无法与正确的签名匹配。3.3 Token 和 JWT 的关系JWT 全称 JSON Web Token它是一种特定的 Token 实现方式也是现在比较主流的一种 Token 实现方式它生成的也是一个 Token但是 JWT 使用 JSON 格式来存储数据并且由于需要存储一些额外的信息因此通常会比普通随机字符串类型的 Token 体积要更大一些。token 生成算法有很多种例如使用HMCA SHA384、HMCA SHA512、RSA、ECDSA等多种加密算法HMAC 对称算法签名验证更快RSAECDSA非对称算法更适合分布式系统或放抵赖场景这些算法的选择取决于具体的业务场景和需求如果需要更高的安全性可以选择非对称 RSA 和 ECDSA如果追求更快的签名速度可以选择 SHCA SHA256 算法。四. Cookie 详解4.1 Cookie 是什么有什么用一句话来说Cooke 是一种客户端存储技术。Cookie 可以用来存储小型数据文件也可以存储 Session 和 Token它是浏览器提供的一种机制。存于用户硬盘的一个文件这个文件通常对应于一个域名当浏览器再次访问这个域名时便使这个 cookie 可用。因此cookie 可以跨越一个域名下的多个网页但不能跨越多个域名使用。举个最直观的例子我在 谷歌浏览器上网浏览谷歌浏览器会生成自己的 Cookie我在 火狐浏览器上网火狐浏览器也会生成自己的 Cookie而不能去访问和操作对方的 Cookie因此Cookie 不能跨越域名。如下图在浏览器中按 F12 并打开 Application在左侧我们就可以看到 Cookies 这一栏这里是全局 Cookie所有的信息都存储在这里。点进去就可以看到里面存储着很多的数据另外就是单个请求的 Cookie如下图所示我们找一个 HTTP 请求打开 Headers可以看到该请求的请求头 Request Header 也携带着 Cookie。4.2 Cookie 的生成流程通常情况下Cookie 的生成分为以下四个步骤1用户首次登录访问网站发送请求到服务器——2服务器发送一个 HTTP Resopnse 响应客户端并将 Cookie 存放到头部——3用户得到服务器响应保存Cookie到浏览器——4后续用户在发送请求到服务器HTTP Request请求头都要携带Cookie然后服务器识别才会响应返回数据。4.3 Cookie 常见属性如下图所示Cookie 中有很多属性我们主要记住比较重要的几个就可以了。namecookie的名称一般用字母和数组表示value即 cookie 的值可以进行加密和解密path访问路径表示可以访问当 cookie 的路径都有哪些/ 表示同一个站点下均可以访问到Expires/Max-Age超时时间/最大存活时就是字面意义上的意思类似 Redis 中对象的TTL超时过期时间HttpOnly布尔属性值用于指示 Cookie 是否只能通过 HTTP 请求发送而不能通过 JavaScript 访问。如果设置了HttpOnly属性那么 JavaScript 就无法访问这个 Cookie从而增加了 Cookie 的安全性。Secure布尔属性用于指示 Cookie 是否只能通过 HTTPS 请求发送。如果设置了Secure属性那么 Cookie 只会在 HTTPS 请求中发送而在 HTTP 请求中不会发送。这可以防止 Cookie 被窃取因为 Cookie 只会在 HTTPS 请求中发送而在 HTTP 请求中不会发送。4.4 Cookie 的安全性问题在 HTTP 中由于 Cookie 是进行明文传输的所以安全性极低。特别是如果在 Cookie 中存储 Token收到网络攻击后对方可以直接获取 Cookie 中的Token登陆进行违法操作。而且Cookie 的大小限制在 4KB 左右对于业务比较发杂的信息是无法携带的所以通常用来存储对安全性不高的简易数据。既然 Cookie 无法存储 Token那么实际开发过程中 Token 存在哪里呢其实是在 Redis 中大致流程如下所示代码省略但思路大致就是这个样子。// 1. 用户首次登录访问验证成功生成 token 签名 // 2. 将 token 存储于服务器的 redis // 3. 将 key user:token:uid 返回给客户端 // 4. 再次访问客户端携带 key 访问接口 // 5. 通过 key 查询 redis 获取 token // 6. 拦截验证 token 签名 // 7. 如果验证成功则放行否则拦截4.5 Cookie 的生命周期Cookie 现在有两种常见的存储级别一种是会话级一种是持久级。会话级Cookie 只保存在客户端浏览器的内存中当我们关闭客服端时 Cookie 就失效了持久级Cookie 会保存在用户的硬盘中直至过期时间结束或者用户主动将其销毁