Cookie、Session、Token 是什么?有什么区别?

Cookie:

Cookie是存储在用户浏览器端的一个小型数据文件,这些数据通常都会记录用户的关键识别信息,Cookie 是由浏览器负责存储的,而不是操作系统,所以,它是 “浏览器绑定” 的,只能在本浏览器内生效。如果你换个浏览器或者换台电脑,新的浏览器里没有服务器对应的 Cookie,服务器也就认不出来了,只能 Set-Cookie。
Cookie 就是服务器委托浏览器存储在客户端里的一些数据,而这些数据通常都会记录用户的关键识别信息。所以, 就需要在 “key=value” 外再用一些手段来保护,防止外泄或窃取,这些手段就是 Cookie 的属性。

属性

生命周期

首先,我们应该设置 Cookie 的生存周期,也就是它的有效期,让它只能在一段时间内可用,一旦超过这个期限浏览器就认为是 Cookie 失效,在存储里删除,也不会发送给服务器。
Cookie 的有效期可以使用 ExpiresMax-Age 两个属性来设置。
“Expires” 俗称 “过期时间”,用的是绝对时间点,可以理解为 “截止日期”(deadline)。“Max-Age” 用的是相对时间,单位是秒,浏览器用收到报文的时间点再加上 Max-Age,就可以得到失效的绝对时间。
Expires 和 Max-Age 可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用 Max-Age 计算失效期。

作用域

其次,我们需要设置 Cookie 的作用域,让浏览器仅发送给特定的服务器和 URI,避免被其他网站盗用。
作用域的设置比较简单,“Domain” 和 “Path” 指定了 Cookie 所属的域名和路径,浏览器在发送 Cookie 前会从 URI 中提取出 host 和 path 部分,对比 Cookie 的属性。如果不满足条件,就不会在请求头里发送 Cookie。使用这两个属性可以为不同的域名和路径分别设置各自的 Cookie

HttpOnly

最后要考虑的就是 Cookie 的安全性了,尽量不要让服务器以外的人看到。
属性 “HttpOnly” 会告诉浏览器,此 Cookie 只能通过浏览器 HTTP 协议传输,禁止其他方式访问,浏览器的 JS 引擎就会禁用 document.cookie 等一切相关的 API,脚本攻击也就无从谈起了。

SameSite

可以防范 “跨站请求伪造”(XSRF)攻击,设置成“SameSite=Strict” 可以严格限定 Cookie 不能随着跳转链接跨站发送,而 “SameSite=Lax” 则略宽松一点,允许 GET/HEAD 等安全方法,但禁止 POST 跨站发送。

Secure

表示这个 Cookie 仅能用 HTTPS 协议加密传输,明文的 HTTP 协议会禁止发送。但 Cookie 本身不是加密的,浏览器里还是以明文的形式存在。

Cookie 的应用

身份识别

保存用户的登录信息,实现会话事务。
比如,你用账号和密码登录某电商,登录成功后网站服务器就会发给浏览器一个 Cookie,内容大概是 “name=yourid”,这样就成功地把身份标签贴在了你身上。
之后你在网站里随便访问哪件商品的页面,浏览器都会自动把身份 Cookie 发给服务器,所以服务器总会知道你的身份,一方面免去了重复登录的麻烦,另一方面也能够自动记录你的浏览记录和购物下单(在后台数据库或者也用 Cookie),实现了 “状态保持”。

广告跟踪

你上网的时候肯定看过很多的广告图片,这些图片背后都是广告商网站(例如 Google),它会 “偷偷地” 给你贴上 Cookie 小纸条,这样你上其他的网站,别的广告就能用 Cookie 读出你的身份,然后做行为分析,再推给你广告。
这种 Cookie 不是由访问的主站存储的,所以又叫 “第三方 Cookie”(third-party cookie)。如果广告商势力很大,广告到处都是,那么就比较“恐怖” 了,无论你走到哪里它都会通过 Cookie 认出你来,实现广告“精准打击”。
为了防止滥用 Cookie 搜集用户隐私,互联网组织相继提出了 DNT(Do Not Track)和 P3P(Platform for Privacy Preferences Project),但实际作用不大。
主要用于保持用户登录状态、跟踪用户行为、存储用户偏好等。

Session:

Session代表服务器与浏览器的一次会话过程,每个用户会话都有一个唯一的 Session ID,并且完全由服务端掌控,实现分配ID、会话信息存储、会话检索等功能。
Session机制将用户的所有活动信息、上下文信息、登录信息等都存储在服务端,只是生成一个唯一标识ID发送给客户端,后续的交互将没有重复的用户信息传输,取而代之的是唯一标识ID,称之为Session-ID。

session的实现

cookieurl重写,而cookie是首选方式,因为各种现代浏览器都默认开通cookie功能,但是每种浏览器也都有允许cookie失效的设置,因此对于Session机制来说还需要一个备胎。
将会话标识号以参数形式附加在超链接的URL地址后面的技术称为URL重写。

#原始的URL: 
http://taobao.com/getitem?name=baymax&action=buy 
#重写后的URL: 
http://taobao.com/getitem?sessionid=1wui87htentg&?name=baymax&action=buy 

由于Session信息是存储在服务端的,因此如果用户量很大的场景,Session信息占用的空间就不容忽视。
对于大型网站必然是集群化&分布式的服务器配置,如果Session信息是存储在本地的,那么由于负载均衡的作用,原来请求机器A并且存储了Session信息,下一次请求可能到了机器B,此时机器B上并没有Session信息。
如果使用服务端共享的存储,比如数据库,但当用户量很大时,大量用户信息存储在数据库,对数据库造成较大了压力,可能导致数据库崩溃。

Token:

Token本质是一种加密的字符串,用于身份验证和授权,可以包含用户信息和权限,用于验证用户身份或授权访问资源。认证后,后端生成Token,由服务端生成并发放给客户端,存储在客户端(浏览器或移动应用中),后续客户端访问服务端需要带上这个Token。
Token避免了Session机制带来的海量信息存储问题,也避免了Cookie机制的一些安全性问题,属于典型的时间换空间的思路。在现代移动互联网场景、跨域访问等场景有广泛的用途。

组成

以JSON Web Token(JWT)为例,Token主要由3部分组成:

Header 头部信息

Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。

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

上面代码中,alg 属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);type 属性表示这个令牌(token)的类型(type),JWT 令牌统一写为 JWT。
最后,将上面的 JSON 对象使用 Base64URL 算法转成字符串。

Payload 净荷信息

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据,记录了用户信息和过期时间等 JWT 规定了 7 个官方字段,供选用。
● iss (issuer):签发人
● exp (expiration time):过期时间
● sub (subject):主题
● aud (audience):受众
● nbf (Not Before):生效时间
● iat (Issued At):签发时间
● jti (JWT ID):编号
除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。

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

注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
这个 JSON 对象也要使用 Base64URL 算法转成字符串。

Signature

Signature 部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

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

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用 “点”(.)分隔,就可以返回给用户。

header和payload的信息不做加密,只做一般的base64编码,服务端收到token后剥离出header和payload获取算法、用户、过期时间等信息,然后根据自己的加密密钥来生成signature,并与客户端的sign进行一致性验证。
这样就实现了用CPU加解密的时间换取存储空间,干净利落,同时服务端密钥的重要性就显而易见,一旦泄露整个机制就崩塌了,这个时候就需要考虑HTTPS了。

使用场景区别:

  1. Cookie:主要用于客户端状态的简单存储和追踪。
  2. Session:用于服务器端的复杂状态管理,特别是在需要存储大量会话数据时。
  3. Token:用于无状态的认证和授权,特别是在分布式和跨域环境下。
    简单来说,Cookie 和Session更适合用于单次会话的认证和状态管理,而Token 更适合用于跨会话的认证和状态管理。

你可能感兴趣的:(计算机网络,计算机网络)