Cookie Session Token JWT的区别和实现原理(1)

一句话总结:Cookie Session Token JWT出现的原因是因为 HTTP 是一个无状态的协议。

我们先来理解两个概念

无状态的HTTP协议

协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。HTTP协议是无状态的协议。意思是一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话

无状态的的好处就是一个字「快」;坏处也很明显,需要借靠 cookie、session 、token等机制将客户端多次请求关联起来。想象一下如果没有 cookie、session、token 这样的机制,我们在网站上每次点击都需要重新输入密码认证,这样槽糕的体验你还愿意继续用吗?

会话(Session)跟踪

会话,指用户登录网站后的一系列动作, 比如用户打开一个浏览器, 点击多个超链接, 访问服务器多个web资源, 然后关闭浏览器, 整个过程称之为一个会话。会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定。

认证、授权

在讲解cookie、session 、token前我们先简单讲解两个概念:认证、授权。

什么是认证?

认证(Authentication)简单来讲就是验证当前者的身份,证明你是你自己

最常见的认证方式是通过用户名和密码,除此之外还有:

• 通过用户手机:手机短信、手机二维码扫描、手势密码.

• 用户的电子邮箱。

• 身份证号码。

• 基于时间序列和用户相关的一次性口令。

• 用户的生物学特征:指纹、语音、眼睛虹膜等。

为了确认用户的身份,防止请求伪造,在安全要求高的场合,经常会使用组合认证(也叫多因素认证),也就是同时使用多个认证方式对用户的身份进行校验。

什么是授权?

授权(Authorization)简单来讲就是授予第三方访问用户资源的权限

在互联网应用开发中,主要通过下面几种方式实现授权:

通过 session 机制,一个访问会话保持着用户的授权信息。

通过 cookie 机制,一个网站的 cookie 保持着用户的授权信息。

颁发授权令牌(token),一个合法有效的令牌中保持着用户的授权信息。

Cookie

由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道用户身份。服务器要想辨别用户身份,怎么办,那就给每个访问我的用户的客户端分配一个通行证,这样服务器就能从通行证上确认客户身份了,这个通行证就是cookie的工作原理。

什么是Cookie?

是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。----百度百科

Cookie实际上是一小段的文本信息。当客户端浏览器请求服务器时,如果服务器需要辨别用户身份,就向客户端浏览器分配一个Cookie。客户端会把Cookie保存在本地。当浏览器再请求该网站(同一台服务器)时,浏览器把请求的网址连同该Cookie一同发送给服务器。服务器检查该Cookie,以此来辨别用户身份。服务器还可以根据需要修改Cookie的内容。

Cookie工作流程

(1)浏览器向服务器发送请求;

(2)服务器响应请求,向客户端浏览器分配一个 Cookie;

(3)浏览器将 Cookie 存在本地,下一次请求时带上该 Cookie;

(4)服务器响应请求。

 设置 Cookie

服务器向客户端发送 Cookie 是通过 HTTP 响应报文实现的,在 Set-Cookie 中设置需要向客户端发送的Cookie,Cookie格式如下:

Cookie的组成

Cookie是一段不超过4KB的小型文本数据,由一个名称(Name)、一个值(Value)和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。其中:

(1)Name/Value:设置Cookie的名称及相对应的值,对于认证Cookie,Value值包括Web服务器所提供的访问令牌。

(2)Expires属性:设置Cookie的生存期。有两种存储类型的Cookie:会话性与持久性。Expires属性缺省时,为会话性Cookie,仅保存在客户端内存中,并在用户关闭浏览器时失效;持久性Cookie会保存在用户的硬盘中,直至生存期到或用户直接在网页中单击“注销”等按钮结束会话时才会失效。

(3)Path属性:定义了Web站点上可以访问该Cookie的目录。

(4)Domain属性:指定了可以访问该 Cookie 的 Web 站点或域。Cookie 机制并未遵循严格的同源策略,允许一个子域可以设置或获取其父域的 Cookie。当需要实现单点登录方案时,Cookie 的上述特性非常有用,然而也增加了 Cookie受攻击的危险,比如攻击者可以借此发动会话定置攻击。因而,浏览器禁止在 Domain 属性中设置.org、.com 等通用顶级域名、以及在国家及地区顶级域下注册的二级域名,以减小攻击发生的范围  。

(5)Secure属性:指定是否使用HTTPS安全协议发送Cookie。使用HTTPS安全协议,可以保护Cookie在浏览器和Web服务器间的传输过程中不被窃取和篡改。该方法也可用于Web站点的身份鉴别,即在HTTPS的连接建立阶段,浏览器会检查Web网站的SSL证书的有效性。但是基于兼容性的原因(比如有些网站使用自签署的证书)在检测到SSL证书无效时,浏览器并不会立即终止用户的连接请求,而是显示安全风险信息,用户仍可以选择继续访问该站点。由于许多用户缺乏安全意识,因而仍可能连接到Pharming攻击所伪造的网站  。

(6)HTTPOnly 属性 :用于防止客户端脚本通过document.cookie属性访问Cookie,有助于保护Cookie不被跨站脚本攻击窃取或篡改。但是,HTTPOnly的应用仍存在局限性,一些浏览器可以阻止客户端脚本对Cookie的读操作,但允许写操作;此外大多数浏览器仍允许通过XMLHTTP对象读取HTTP响应中的Set-Cookie头 。

注意

cookie 是不可跨域的: 每个 cookie 都会绑定单一的域名(包括子域),无法在别的域名下获取使用,好比浏览器访问百度不会带上谷歌的cookie。

session

什么是session?

session 翻译过来就是会话。用户打开一个浏览器, 点击多个超链接, 访问服务器多个web资源, 然后关闭浏览器, 整个过程称之为一个会话

Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。每个客户端访问服务器都会建立一个session,那服务器是怎么标识客户端的唯一身份呢?事实上,客户端与服务器建立连接的同时,服务器会自动为其分配一个SessionId。通常将 sessionId 存储在客户端的 cookie 中,客户端每次请求携带 sessionId 即可识别用户。

session 工作流程

(1)用户第一次请求时,提交用户名和密码等信息进行登录认证,服务器根据用户提交的信息进行鉴权,鉴权成功后创建 session 对象,并将 sessionId 塞入 cookie 中,浏览器收到响应信息将 cookie 存入本地;

(2)用户第二次请求时,浏览器自动将当前域名下的 cookie 信息发送给服务端,服务端解析 cookie,获取到 sessionId 后再查找对应的 session 对象,如果 session 对象存在说明用户已经登录,继续下一步操作。 

session的创建过程

当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了sessionId,如果已包含则说明以前已经为此客户端创建过session,服务器就按照sessionId把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含sessionId,则为此客户端创建一个session并且生成一个与此session相关联的sessionId,sessionId的值是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionId将被在本次响应中返回给客户端保存。

禁用cookie和session共享

禁用cookie

如果客户端禁用了cookie,通常有两种方法实现session而不依赖cookie。

1)URL重写,就是把sessionId直接附加在URL路径的后面。

2)表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如:

<form name="testform" action="/xxx">

<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">

<input type="text">

</form> 

session共享

对于多网站(同一父域不同子域)单服务器,我们需要解决的就是来自不同网站之间SessionId的共享。由于域名不同(aaa.test.com和bbb.test.com),而SessionId又分别储存在各自的cookie中,因此服务器会认为对于两个子站的访问,是来自不同的会话。解决的方法是通过修改cookies的域名为父域名达到cookie共享的目的,从而实现SessionId的共享。带来的弊端就是,子站间的cookie信息也同时被共享了

cookie 和 session 的区别

(1)存储位置不同:session 存储在服务器端;cookie 存储在浏览器端;

(2)安全性:cookie安全性一般,在浏览器存储,可以被伪造和修改;

(3)容量和个数限制:很多浏览器限制单个 cookie 保存的数据不能超过4K,一个站点最多保存20个cookie,session 没有类似的限制;

(4)存储的多样性:session 可以存储在 Redis 中、数据库中、应用程序中;而 cookie 只能存储在浏览器中;

(5)生存周期不同: cookie 可设置为长时间保持,Session 一般失效时间较短,一般客户端关闭 session 就会失效;

希望本文章对您有帮助,您的转发、点赞是我的创作动力,十分感谢。更多好文推荐,请关注我的微信公众号--JustJavaIt
原文地址:https://www.cnblogs.com/liaowenhui/p/15390218.html