Session,Cookie和token的关系

本文转载自看完这篇 Session、Cookie、Token,和面试官扯皮就没问题了html

本文脉络以下web

Session和Cookie

HTTP协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录;Session和Cookie的主要目的就是为了弥补HTTP的无状态特性面试

Session是什么

客户端请求服务端,服务端会为此次请求开辟一块内存空间,这个对象即是Session对象,存储结构为ConcurrentHashMap.Session弥补了HTTP无状态特性,服务器能够利用Session存储客户端在同一个会话期间的一些操做记录算法

Session如何判断是否在同一个会话

服务器第一次接收到请求时,开辟了一块Session空间(建立了Session对象),同时生成了一个sessionId,并经过响应头的Set-Cookie:JSESSIONID=XXXXXX命令,向客户端发送要求配置Cookie的相应;客户端收到响应后,在本机客户端设置了一个JSESSIONID=XXXXXXX的Cookie信息,该Cookie的过时事件为浏览器会话结束数据库

接下来客户端每次向同一个网站发送请求时,请求头都会带上该Cookie信息(包含sessionId),而后,服务器经过读取请求头中的Cookie信息,获取名称为JSESSIONID的值,获得这次请求的sessionId跨域

Session的缺点

Session机制有个缺点-------不支持单点登陆;好比A服务器存储了Session,就是作了负载均衡后,加入一段事件内A的访问量激增,会转发到B进行访问,可是B服务器并无访问A的Session,会致使Session的失效浏览器

Cookies是什么?

HTTP 协议中的 Cookie 包括 Web Cookie浏览器 Cookie,它是服务器发送到 Web 浏览器的一小块数据。服务器发送到浏览器的 Cookie,浏览器会进行存储,并与下一个请求一块儿发送到服务器。一般,它用于判断两个请求是否来自于同一个浏览器,例如用户保持登陆状态。安全

HTTP Cookie 机制是 HTTP 协议无状态的一种补充和改良服务器

Cookie 主要用于下面三个目的cookie

  • 会话管理

登录、购物车、游戏得分或者服务器应该记住的其余内容

  • 个性化

用户偏好、主题或者其余设置

  • 追踪

记录和分析用户行为

Cookie 曾经用于通常的客户端存储。虽然这是合法的,由于它们是在客户端上存储数据的惟一方法,但现在建议使用现代存储 API。Cookie 随每一个请求一块儿发送,所以它们可能会下降性能(尤为是对于移动数据链接而言)。

建立Cookie

当接收到客户端发出的 HTTP 请求时,服务器能够发送带有响应的 Set-Cookie 标头,Cookie 一般由浏览器存储,而后将 Cookie 与 HTTP 标头一同向服务器发出请求。

Set-Cookie和Cookie标头

Set-Cookie HTTP 响应标头将 cookie 从服务器发送到用户代理。下面是一个发送 Cookie 的例子

此标头告诉客户端存储 Cookie

如今,随着对服务器的每一个新请求,浏览器将使用 Cookie 头将全部之前存储的 Cookie 发送回服务器

有两种类型的 Cookies,一种是 Session Cookies,一种是 Persistent Cookies,若是 Cookie 不包含到期日期,则将其视为会话 Cookie。会话 Cookie 存储在内存中,永远不会写入磁盘,当浏览器关闭时,此后 Cookie 将永久丢失。若是 Cookie 包含有效期 ,则将其视为持久性 Cookie。在到期指定的日期,Cookie 将从磁盘中删除。

还有一种是 Cookie的 Secure 和 HttpOnly 标记,下面依次来介绍一下

会话Cookies

上面的示例建立的是会话 Cookie ,会话 Cookie 有个特征,客户端关闭时 Cookie 会删除,由于它没有指定ExpiresMax-Age 指令。

可是,Web 浏览器可能会使用会话还原,这会使大多数会话 Cookie 保持永久状态,就像从未关闭过浏览器同样。

永久性Cookies

永久性 Cookie 不会在客户端关闭时过时,而是在特定日期(Expires)特定时间长度(Max-Age)外过时。例如

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

Cookie的Secure和HttpOnly标记

安全的 Cookie 须要通过 HTTPS 协议经过加密的方式发送到服务器。即便是安全的,也不该该将敏感信息存储在cookie 中,由于它们本质上是不安全的,而且此标志不能提供真正的保护。

HttpOnly的做用

  • 会话 Cookie 中缺乏 HttpOnly 属性会致使攻击者能够经过程序(JS脚本、Applet等)获取到用户的 Cookie 信息,形成用户 Cookie 信息泄露,增长攻击者的跨站脚本攻击威胁。
  • HttpOnly 是微软对 Cookie 作的扩展,该值指定 Cookie 是否可经过客户端脚本访问。
  • 若是在 Cookie 中没有设置 HttpOnly 属性为 true,可能致使 Cookie 被窃取。窃取的 Cookie 能够包含标识站点用户的敏感信息,如 ASP.NET 会话 ID 或 Forms 身份验证票证,攻击者能够重播窃取的 Cookie,以便假装成用户或获取敏感信息,进行跨站脚本攻击等。

Cookie的做用域

DomainPath 标识定义了 Cookie 的做用域:即 Cookie 应该发送给哪些 URL。

Domain 标识指定了哪些主机能够接受 Cookie。若是不指定,默认为当前主机(不包含子域名)。若是指定了Domain,则通常包含子域名。

例如,若是设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如developer.mozilla.org)。

例如,设置 Path=/docs,则如下地址都会匹配:

  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

JSON Web Token和Session Cookies的对比

JSON Web Token ,简称 JWT,它和 Session均可觉得网站提供用户的身份认证,可是它们不是一回事。

下面是 JWT 和 Session 不一样之处的研究

JWT和Session Cookies的相同之处

在探讨 JWT 和 Session Cookies 以前,有必要须要先去理解一下它们的相同之处。

它们既能够对用户进行身份验证,也能够用来在用户单击进入不一样页面时以及登录网站或应用程序后进行身份验证。

若是没有这二者,那你可能须要在每一个页面切换时都须要进行登陆了。由于 HTTP 是一个无状态的协议。这也就意味着当你访问某个网页,而后单击同一站点上的另外一个页面时,服务器的内存中将不会记住你以前的操做。

什么是Json Web Tokens

Json Web Token 的简称就是 JWT,一般能够称为 Json 令牌。它是RFC 7519 中定义的用于安全的将信息做为 Json 对象进行传输的一种形式。JWT 中存储的信息是通过数字签名的,所以能够被信任和理解。可使用 HMAC 算法或使用 RSA/ECDSA 的公用/专用密钥对 JWT 进行签名。

使用 JWT 主要用来下面两点

  • 认证(Authorization):这是使用 JWT 最多见的一种状况,一旦用户登陆,后面每一个请求都会包含 JWT,从而容许用户访问该令牌所容许的路由、服务和资源。单点登陆是当今普遍使用 JWT 的一项功能,由于它的开销很小。
  • 信息交换(Information Exchange):JWT 是可以安全传输信息的一种方式。经过使用公钥/私钥对 JWT 进行签名认证。此外,因为签名是使用 headpayload 计算的,所以你还能够验证内容是否遭到篡改。

JWT的格式

下面,咱们会探讨一下 JWT 的组成和格式是什么

JWT 主要由三部分组成,每一个部分用 . 进行分割,各个部分分别是

  • Header
  • Payload
  • Signature

所以,一个很是简单的 JWT 组成会是下面这样

而后咱们分别对不一样的部分进行探讨。

Header

Header 是 JWT 的标头,它一般由两部分组成:令牌的类型(即 JWT)和使用的 签名算法,例如 HMAC SHA256 或 RSA。

例如

{
  "alg": "HS256",
  "typ": "JWT"
}

指定类型和签名算法后,Json 块被 Base64Url 编码造成 JWT 的第一部分。

Payload

Token 的第二部分是 Payload,Payload 中包含一个声明。声明是有关实体(一般是用户)和其余数据的声明。共有三种类型的声明:registered, public 和 private 声明。

  • registered 声明:包含一组建议使用的预约义声明,主要包括

  • public 声明:公共的声明,能够添加任何的信息,通常添加用户的相关信息或其余业务须要的必要信息,但不建议添加敏感信息,由于该部分在客户端可解密。
  • private 声明:自定义声明,旨在在赞成使用它们的各方之间共享信息,既不是注册声明也不是公共声明。

例如

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

而后 payload Json 块会被Base64Url 编码造成 JWT 的第二部分。

signature

JWT 的第三部分是一个签证信息,这个签证信息由三部分组成

  • header (base64后的)
  • payload (base64后的)
  • secret

好比咱们须要 HMAC SHA256 算法进行签名

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

签名用于验证消息在此过程当中没有更改,而且对于使用私钥进行签名的令牌,它还能够验证 JWT 的发送者的真实身份

拼凑在一块儿

如今咱们把上面的三个由点分隔的 Base64-URL 字符串部分组成在一块儿,这个字符串能够在 HTML 和 HTTP 环境中轻松传递这些字符串。

下面是一个完整的 JWT 示例,它对 header 和 payload 进行编码,而后使用 signature 进行签名

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

img

若是想本身测试编写的话,能够访问 JWT 官网 https://jwt.io/#debugger-io

JWT 和 Session Cookies 的不一样

JWT 和 Session Cookies 都提供安全的用户身份验证,可是它们有如下几点不一样

密码签名

JWT 具备加密签名,而 Session Cookies 则没有。

JSON 是无状态的

JWT 是无状态的,由于声明被存储在客户端,而不是服务端内存中。

身份验证能够在本地进行,而不是在请求必须经过服务器数据库或相似位置中进行。这意味着能够对用户进行屡次身份验证,而无需与站点或应用程序的数据库进行通讯,也无需在此过程当中消耗大量资源。

可扩展性

Session Cookies 是存储在服务器内存中,这就意味着若是网站或者应用很大的状况下会耗费大量的资源。因为 JWT 是无状态的,在许多状况下,它们能够节省服务器资源。所以 JWT 要比 Session Cookies 具备更强的可扩展性

JWT 支持跨域认证

Session Cookies 只能用在单个节点的域或者它的子域中有效。若是它们尝试经过第三个节点访问,就会被禁止。若是你但愿本身的网站和其余站点创建安全链接时,这是一个问题。

使用 JWT 能够解决这个问题,使用 JWT 可以经过多个节点进行用户认证,也就是咱们常说的跨域认证

JWT 和 Session Cookies 的选型

咱们上面探讨了 JWT 和 Cookies 的不一样点,相信你也会对选型有了更深的认识,大体来讲

对于只须要登陆用户并访问存储在站点数据库中的一些信息的中小型网站来讲,Session Cookies 一般就能知足。

若是你有企业级站点,应用程序或附近的站点,而且须要处理大量的请求,尤为是第三方或不少第三方(包括位于不一样域的API),则 JWT 显然更适合。

后记

前两天面试的时候问到了这个题,因此写篇文章总结一下,还问到了一个面试题,禁用 Cookies,如何使用 Session ?网上百度了一下,发现这是 PHP 的面试题,em…

img

但仍是选择了解了一下,如何禁用 Cookies 后,使用 Session

  • 若是禁用了 Cookies,服务器仍会将 sessionId 以 cookie 的方式发送给浏览器,可是,浏览器再也不保存这个cookie (即sessionId) 了。
  • 若是想要继续使用 session,须要采用 URL 重写 的方式来实现,能够参考 https://www.cnblogs.com/Renyi-Fan/p/11012086.html