【前端知识】Cookie, Session,Token和JWT的发展及区别(一)

五一假期第3天,2023年5月1日继续打卡分享自己的前端笔记😜,今天就分享我关于Cookie, Session,Token和JWT的相关笔记和理解吧。本文为原创,未经同意请勿转载

由于篇幅有点长😂,所以笔者将我关于这部分的笔记分为四个篇章(文章开头后面附录上下篇链接),避免读者的阅读疲倦感😵,同时也方便大家的阅读啦🤗。如果下面笔记中存在错误,欢迎大家及时指正,学习与讨论。

1. 背景

首先,先介绍Cookie/Session/Token/JWT它们出现的一个背景(更加准确的描述其实应该是Cookie出现的背景),也就是HTTP的无状态属性。

众所周知,我们访问网页一般都是使用HTTP/HTTPS协议,然而HTTP是一种不保存状态,即无状态协议。那什么是无状态呢?也就是这一次请求和上一次请求是没有任何关联的。这种无状态的好处就是可以快速响应。但是如果服务端需要辨别请求时哪个客户端发送,或者需要关联两个请求/响应时,就需要获取请求或者响应的状态,因此这种无状态便无法满足我们的需求了。因此,为了使某个域名下的所有网页能够共享某些状态数据,引申出了Cookie和Session。

💡总结而言
由于HTTP是无状态协议,不保存通信状态,无法标识客服端,所以Cookie、Session和Token都是用来解决这个问题的(做持久化处理的),目的就是让客户端,也就是浏览器和服务端互相认识。

Cookie、Session、Token和JWT都是用于标识客户端的,而且从发展上来看可以看成网络安全的一个发展吧。那它们之间有什么区别,下面笔者我将详细对每一个部分展开说明。

2. Cookie

2.1 Cookie的定义

首先,Cookie由服务器创建的,只保存在浏览器中的小型文本文件,格式为key=value,一般包含用户信息,登录及访问权限等。

2.2 Cookie的特点

👍2.2.1 Cookie的特点

(1)由服务器生成并存储在客户端的
(2)以普通文本方式存储键值对数据,无法执行代码
(3)不可跨域:每个Cookie会绑定单一的域名,无法在别的域名下使用,一级域名和二级域名之间是允许共享使用的(靠的是 domain)。同一个域名下的不同页面之间可以共享Cookie,同域名不同端口也是允许共享使用的。
(4)有过期时限:Cookie会在过期时间到达之后自动删除
(5)文件体积大小,数量有限制:一般在4KB左右,数量在50个左右
(6)自动发送
(7)只能存储String 类型的对象

👀2.2.2 Cookie保存的位置

  • 在HTTP通信中的数据位置——置于HTTP请求头和响应头
    • HTTP请求:Cookie 通常是放在 HTTP 请求头中的 Cookie字段中。
    • HTTP响应:Cookie通常放在http响应的Set-Cookie字段中。
  • 存储位置:客户端

2.3 Cookie的一些重要属性

✨2.3.1 Cookie的重要属性

Cookie集合中的每个Cookie都拥有下面这些重要的属性,而且每个Cookie的这些属性都是独立分开的,各自控制各自的Cookie。

  • 数据类型:在Cookie中,设置键值对的键名name和键值value都必须是字符串类型,如果是Unicode
    字符,需要为字符编码;如果值为二进制数据,则需要使用 BASE64 编码。

  • domain:指定 Cookie 所属域名,默认是当前域名

  • path: 指定 Cookie 在哪个路径(路由)下生效,默认是 ‘/’

  • maxAge: Cookie 失效的时间,单位秒,默认为 -1。如果为正数,则该 Cookie 在 maxAge 秒后失效。如果为负数,该 Cookie 为临时 Cookie ,关闭浏览器即失效,浏览器也不会以任何形式保存该 Cookie 。如果为 0,表示删除该 Cookie 。

  • secure :设置Cookie是否使用安全协议传输。安全协议有 HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。当 secure 值为 true 时,Cookie 在 HTTP 中是无效,在 HTTPS 中才有效。

  • HttpOnly如果给某个 Cookie 设置了HttpOnly属性,则无法通过 JS 脚本 读取到该Cookie 的信息,但还是能通过 Application 中手动修改 Cookie,所以只是在一定程度上可以防止 XSS 攻击,不是绝对的安全

  • SameSite:设置Cookie在跨域请求的时候不能被发送。

🎇2.3.2 Cookie的有效期,max-age和作用域,domain

  • 默认有效期:虽然客户端计算机上 Cookie 的持续时间还取决于客户端上的 Cookie 过期处理和用户干预,但Cookie默认的有效期是短暂的,即Cookie只能维持在Web浏览器的会话期间,一旦用户关闭浏览器,Cookie保存的数据就丢失了。
  • 默认有效期作用域:Cookie的作用域不是局限在浏览器的单个窗口中,它的有效期和整个浏览器进程而不是单个浏览器窗口的有效期一致。
  • max-age设置——>数据持久性:要知道Cookie的优点还有数据持久性,那这不是跟上面的有效期短暂矛盾了吗?其实不然。数据持久性不是指在默认有效期的情况下,而是由于max-age的设置,所以Cookie具有数据持久性的特点是基于max-age的。一旦设置了有效期,浏览器就会将Cookie数据存储在一个文件中,并且直到过了指定的有效期才会删除该文件。这个到期时间可以是具体的日期时间也可以是相对时间,这样就让 Cookie 能够在指定时间范围内存在,从而实现数据持久化。
  • 作用域:Cookie的作用域默认由文档源限制,可以通过文档源和文档路径来确定的。该作用域通过Cookie的path和domain属性也是可配置的。默认情况下,Cookie和创建它的Web页面有关,并对该Web页面以及和该Web页面同目录或者子目录的其他Web页面可见。
  • domain设置——>同域子域名可访问:在没有设置 domain 的情况下,默认 Cookie 只设置在当前域名下。当然我们可以设置domain属性,但是需要注意domain只能设置为当前服务器的域名,也就是这个 domain 只能是当前域名的上级域名,这样上级域名相同的网站就都能读取到这个Cookie了。比如:我在网站 aa.ryDomain.com 下设置 cookie:“myName=xiaobai_Ry; domain=.ryDomain.com”,这样在 bb.ryDomain.com 下也能读取到 myName=xiaobai_Ry。

2.4 Cookie的认证流程

在这里插入图片描述

  • 认证流程简述:在用户第一次访问网站服务器时,服务器会通过响应头Set-Cookie字段发给浏览器,浏览器接收后会把Cookie信息以键值对的形式保存到浏览器本地某个txt文件中。在后面访问的时候,浏览器就都会将保存的Cookie发送给服务器,以此让服务器识别身份(让服务器知道这个请求来自于哪个客户端)。
    一个例子

    Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Mon, 01 May 2023 14:00:00 GMT;HttpOnly;secure"
    

    📢注意: 这里需要注意的一点是客户端第一次向浏览器请求时,携带的Cookie是空的(也就是相当于没有Cookie),响应页面也没有给Cookie设置,所以Cookie实际上就是在服务器中设置和生成的,并返回给客户端保存

  • 认证流程步骤叙述发布——》检索——》验证
    1、发布:当用户想要访问和使用网站里经过认证的资源时,Web服务器会检测与核查用户是否提供了cookie,对用户的请求进行审核与验证。
    2、检索:用户提出了访问请求,客户端浏览器会检索与用户请求相匹配的Cookie。
    3、验证:Web服务器会验证是否有访问令牌,如果有访问令牌的话,则同意用户的请求,如果没有这个令牌,则会拒绝用户的访问和登录请求。

2.5 Cookie的优缺点及常用场景

😎2.5.1 优点

  • 优点总结:极高的扩展性和可用性,便于使用、实现和管理,占用内存少,具有可持久性,透明性。
  • 优点展开
    • 简单性,便于使用和实现:Cookie是一种基于文本,以键值对形式存储数据的轻量结构,数据形式简单,实现Cookie的使用要比其他协议更加简单容易。
    • 轻量化,占用内存少,不需要任何服务资源:Cookie 存储在客户端并在发送后由服务器读取,因此不会给服务器带来额外的负担。
    • 数据持久性和稳定性:虽然客户端计算机上 Cookie 的持续时间取决于客户端上的 Cookie 过期处理和用户干预,Cookie 通常是客户端上持续时间最长的数据保留形式。这也是Cookie很大的一个优点所在。当在客户端的浏览器上设置Cookie时,它可以持续数天,数月甚至数年。这样可以轻松保存用户首选项和访问信息,并在用户每次返回站点时保持此信息可用。另外,由于Cookie存储在客户端的硬盘上,因此如果服务器崩溃,它们仍然可用。
    • 透明性:Cookie以明文形式存储,透明地工作,用户不知道需要存储的信息。
    • 灵活性,可配置到期规则,可通过加密和安全传输计数来提高Cookie安全性:Cookie 可以在浏览器会话结束时到期,或者可以在客户端计算机上无限期存在,这取决于客户端的到期规则。通过加密和安全传输技术(ssl),可以减少Cookie被破解的可能性。
    • 易于管理:Cookie存储在用户硬盘驱动器上的Cookie.txt下的文本文件中,因为它是一个文本文件,我们可以使用任何查看器或文本编辑器来显示,编辑和删除它们。
    • 可跨页面传输数据(注:同域:Cookie 可以在同一个网站的不同页面之间传递数据,比如购物车中的商品信息
    • 可保存用户状态信息:Cookie 可以将用户的登录状态保存在浏览器中,避免了每次访问页面都需要重新验证身份的问题。
    • 提高用户体验:例如记录用户的偏好设置,可以为用户提供更加个性化的服务。

🤢2.5.2 缺点

  • 缺点总结:虽然Cookie简单便于管理,但是Cookie存在隐私隐患,安全性问题,禁用限制问题和大小及访问限制等问题。
  • 缺点展开
    • 隐私泄漏问题:启用Cookie的Web浏览器会跟踪访问过的所有网站。这意味着,经许可(或不在Google的情况下),第三方(广告商,其他用户,甚至黑客)可以访问这些Cookie存储的信息。因此,Cookie 存储的用户信息可能违背用户的隐私权,因此应该尽量少用无关信息的 Cookie,且应该经过用户同意后再进行存储。
    • 安全性问题:由于Cookie 存储在客户端,并且是以明文形式存储,所以Cookie中存储的数据可能被其他人窃取或者篡改,特别是在使用不安全网络时。Cookie很容易受到CSRF(跨站请求伪造)攻击。
    • 大小数量限制问题:每个Cookie 文本的大小和数量有所限制,一般情况下体积大小不能超过4kb,如果超过会被截掉,因此无法存储大量的信息。此外,Cookie仅限于简单的字符串信息,他们无法存储复杂的信息。Cookie的数量也存在一些限制,不同浏览器限制不同:
      • IE6及以下的版本最多20个Cookie
      • IE7以后的可以有50个Cookie
      • Firefox可以有50个Cookie
      • Chrome和Safri没有限制
    • 禁用限制问题:Cookie可以被浏览器禁用,当浏览器选择禁用Cookie模式,意味着用户可以决定不在其浏览器上使用Cookie,这可能会在浏览器的运行中产生一些问题。
    • 访问限制问题(主要指跨域:Cookie 是不可跨域的,要实现跨域需要使用Token等。此外,Cookie与浏览器相关,不能互相访问。
    • 加密解密困难问题:可以手动加密和解密Cookie来提高Cookie安全性,但由于加密和解密需要额外的编码,并且加密和解密需要时间,因此会影响应用程序的性能。
    • 有些状态不可能保存在客户端:如,为了防止重复提交表达,需要在服务器端保存一个计时器,如果把这个计时器保存在客户端,它将不起作用。

✍2.5.3 作用及常用场景

  • 常用场景总结:(1)登录状态及用户信息的管理;(2)跟踪用户行为,统计分析,广告定位;(3)记住用户偏好设置,定制页面;(4)创建购物车;(5)缓存数据,用于搜索历史和浏览记录;(6)跨页面数据传递,实现数据共享与同步 …
  • 展开
    • 登录状态及用户信息的管理——》用户身份认证,登录状态保持:用户登录和用户信息管理是常见的功能。可以使用 cookie 来存储用户登录状态信息,例如用户的登录凭证、用户信息等。通过 Cookie,可以在客户端和服务器之间传递用户信息,实现用户登录状态的保持,避免了每次访问页面都需要重新验证身份的问题。
    • 跟踪用户行为(自动性)——》统计分析,统计用户访问网站的习惯,广告定位:通过记录用户行为等信息,跟踪用户的访问、页面浏览、点击等数据,进行统计分析,根据这些统计分析信息,可以为客户提供定制化的上网服务。同时,广告商也可借此为向用户展示相关的广告。
    • 记住用户偏好设置(设置性/被动)——》定制页面,提供个性化服务:可以使用 Cookie 来存储用户的偏好设置信息来提供个性化的服务,例如用户的语言、主题等,使得用户下次打开浏览器时可以继续使用之前的偏好设置。
    • 缓存数据——》用于搜索历史和浏览记录,减少服务器压力:可以使用 Cookie 来存储搜索历史和浏览记录等信息,提高网站的性能。比如自动填写表单场景,如果用户曾经输入过某些信息,那么这些信息可以被保存在 Cookie 中,在用户返回该页面时可以自动带出。
    • 跨页面数据传递——》实现数据的共享与同步:Cookie 可以在同一个网站的不同页面之间传递数据,比如购物车中的商品信息。
    • 经典场景之购物车:Cookie购物车一般指网站上的电子商务功能,在用户浏览产品后,将所选商品信息保存到浏览器的Cookie中,并在结账时读取Cookie中的信息以便显示或更新所选商品内容和数量。通常情况下,Cookie购物车还会在用户离开网站后保存所选商品信息,以便用户下次访问同一网站时继续购物,或在用户登录到网站时提供更个性化的服务。然而,由于安全原因,有些用户可能不愿意让浏览器储存他们的个人信息(例如地址和支付方式),因此一些商家采用了其他方法来保存购物车内容。需要注意的是,使用 Cookie 存储数据时应当注意数据的安全性和敏感性。敏感信息,例如用户的密码、支付信息等,不应当存储在Cookie中,而应当使用更加安全的方式

2.6 Cookie可能面临的挑战

面临的挑战当然也包括Cookie的缺点,这里就不再赘述,这里主要讲一下禁用限制问题的解决方法:

2.6.1 客户端禁用 Cookie 首部时,如何传递 Cookie 信息?

可以将 Cookie 信息放到 URL的 params 中或者请求的 body 中,但一般的解决方案是放在 url 的 params 中,通过重写 URL的方式传递。

由于Cookie可以被人为的禁止,必须有其他机制以便在Cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把Session id直接附加在URL路径的后面,附加方式也有两种:

  • 一种是作为URL路径的附加信息,表现形式为http://…/xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
  • 另一种是作为查询字符串附加在URL后面,表现形式为
    http://…/xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
    这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。

2.7 怎么检查Cookie是否启用/禁用

前面我们讲了Cookie是可以被人为禁止的,那我们确保在执行我们的Cookie是可用的?通过判断是否禁用来选择不同的解决方案。

要检查浏览器是否禁用Cookie,可以使用JavaScript中的navigator.cookieEnabled属性来判断。这个属性返回布尔值,指示浏览器是否允许Cookie,如果值为true,则当前Cookie是启用的;反之则可能是禁用的

if (navigator.cookieEnabled) {
   alert("Cookies are enabled");
} else {
   alert("Cookies are disabled");
}

这里需要注意有2点
(1)这种方法并不能完全确定用户的浏览器是否完全禁用了Cookie。因为有一些非持久化的cookie仍然可以在当前浏览器会话生命周期内使用,即使用户明确禁用了所有cookie。
(2)返回false时并不意味着用户明确禁用了Cookie。 还可能存在其他因素干扰Cookie,例如隐私设置或运行安全软件等。

💡 因此,在实际开发中,使用navigator.cookieEnabled属性来判断是否启用Cookie并不可靠。更好的方法是尝试写入一个持久化的Cookie,如果成功则表示用户的浏览器支持Cookie。否则,建议提醒用户在其浏览器设置中启用Cookie功能。

2.8 Cookie的读写

💻2.8.1 客户端对Cookie的读取及相关操作

在Web中,客户端对Cookie的操作主要包括读取和设置(修改更新和删除等)。

(1)读取Cookie
通过document.cookie属性可以访问当前页面所有存在的Cookie信息,比如:

var cookies = document.cookie;

document.cookie返回值为一个字符串,该字符串有一系列键/值对组成,比如:

"fryname1=value1; fryname2=value2"

其中每个Cookie用分号(;)隔开,而每个Cookie的键和值用等号(=)隔开。而且返回的每个Cookie值并不包含键/值以外的其他Cookie属性。

如果要获取某个特定Cookie的值,可以采用字符串截取或者正则表达式进行匹配。例如,获取名为fryname2的Cookie值:

var cookies = document.cookie;
var cookieValue = null;
if (cookies && cookies !== '') {
    var cookieArray = cookies.split(';');
    for (var i = 0; i < cookieArray.length; i++) {
        var cookie = cookieArray[i].trim();
        if (cookie.substring(0, 8) === 'fryname2') {
            cookieValue = cookie.substring(9, cookie.length);
            break;
        }
    }
}
console.log(cookieValue);

(2)设置Cookie相关属性
通过JavaScript可以向客户端设置Cookie值。可以使用document.cookie来设置Cookie的相关属性。

document.cookie = "key=value;expires=date;path=path;domain=domain;secure";

由于Cookie的键/值中的值是不允许包含分号、逗号和空白符,因此,在存储前一般可以采用 encodeURIComponent() 函数对值进行编码。相应的,读取cookie值的时候要用 decodeURIComponent() 函数解码。

(3)更新cookie
要更新一个 Cookie,可以直接覆盖它。例如,若有一个名为 oldCookie 的Cookie,并想将它的值设为 newCookieValue,则可以:

document.cookie = 'oldCookie=newCookieValue';

这样子便可直接覆盖旧Cookie 的所有属性,包括它的到期时间和路径。但如果只是更新某个值,则分别指定新的值便可。

(4)删除cookie
要删除一个Cookie,可以通过设置它的过期时间来实现。
可以将过期时间设置为任何早于当前时间的日期,这样子就可以立即将 Cookie 删除。下面以为删除fryname2对应的Cookie为例子:

document.cookie = 'fryname2=; expires=' + new Date(0).toUTCString();

expires 属性设置为 0(也可以设置为日期对象,但是要比当前时间早),表示该 Cookie 已经过期了。当然,除了设置 expires 属性,我们也可以通过设置max-age 属性为 0 来实现(现在更多用的是max-age属性,max-age属性的精确度更高,更加稳定)。注意,我们还有一个空值 fryname2=,这是把 value 设置为空的方法。

补充:
expiresmax-age都用来设置Cookie的有效时间,expires 是指定一个日期与客户端本地的时间进行比较,max-age类似倒计时,Cookie在设置后的若干毫秒内有效。本地的时间是可以被修改的,而同一台服务器的时间总是相同的,因此max-ageexpires 更加稳定可靠。

此外,还可以进一步通过设置pathdomain属性来选择删除Cookie,因为它们允许选择性地删除指定域名下的Cookie。

// 要删除的 cookie 名称
var cookieName = "ryCookie";

// 设置 cookie 过期时间为过去的时间,让浏览器自动删除该 cookie
document.cookie = cookieName + "=;expires=Mon, 01 May 2023 14:00:00 UTC;path=/;domain=example.com";

在上面的代码中,将 path 设置为 “/”,这将使得浏览器删除主域名下所有具有相同名称的Cookie。如果只想删除某个子目录下的Cookie,则需要将 path 设置为该子目录路径。同样的,需要注意将 domain 替换为特定的域名。

👩‍💻2.8.2 服务端对Cookie的设置

在Web中,服务端对Cookie的操作主要包括创建和读取。
(1)创建Cookie
当服务器向客户端发送HTTP响应时,在响应头中可以包含Set-Cookie字段来创建一个新的Cookie。下面是一个用 Node.js 代码创建一个名称为“ryCookie”的Cookie,并将其值设为“hello world”和持续时间为10秒钟的示例:

var http = require('http');
http.createServer(function(req, res) {
    res.setHeader('status', '200 OK');
    res.setHeader('Set-Cookie', 'ryCookie=hello%20world;Max-Age=10'); // 这里创建
    res.write('Hello World');
    res.end();
}).listen(8080);
console.log('running localhost:8080')

如果想设置多个cookie,在设置时可以将多个cookie存放在数组中,例如:

// 存储name为username,value为xiaobaiRy的cookie,过期时间为一小时后
const cookie1 = 'username=xiaobaiRy; Max-Age=3600'; 
// 存储name为user_id,value为123456的cookie
const cookie2 = 'user_id=123456'; 
res.setHeader('Set-Cookie', [cookie1, cookie2]);

(2)读取Cookie
当客户端向服务器发出HTTP请求时,其中可能包含它之前由该服务器设置的Cookies。在Node.js中,可以通过request对象的headers属性访问所有HTTP头信息,所以读取Cookies信息可以:

const cookies = request.headers.cookie;

3. 下篇章笔记

通过上面的知识,我们也对背景和Cookie有了一个大概的了解,所以在中篇中,笔者我将主要介绍一下Session的相关要点以及Session和Cookie的区别。
笔记链接:【前端知识】Cookie, Session,Token和JWT的发展及区别(二)
码字不易,可能当中存在某些字体错误(笔者我没有发现),如果有错误,欢迎大家指正。🤗

  • 22
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaobai_Ry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值