什么是Cookie、令牌与JWT?

在这篇博文中,我们将了解什么是网络 Cookie 和令牌以及它们的用途。我们还将介绍最常见的网络 Cookie 和令牌类型。

什么是 Cookie?
首先,让我们尝试了解什么是网络 Cookie 以及我们如何使用它们。本文中的通用术语 Cookie 指的是网络 Cookie。

Cookie 是小型文本文件这些 Cookie 由您访问的网站(Web 服务器)创建并存储在您的设备中。我们都遇到过它们。几乎您访问的每个网站都会使用 Cookie 横幅“欢迎”您。Cookie 的用途取决于 Cookie 的类型以及网站希望 Cookie 执行的操作。例如,在线商店可以使用 Cookie 来跟踪用户在其网站上的活动、他们访问的最后一个页面、您选择的语言、用户查看过的商品以及他放入购物车的商品。当用户离开网站但稍后返回时,网站可以读取 Cookie 并继续用户离开的地方。但并非所有 Cookie 都具有相同的用途。

我们为何需要 cookie?
因为 HTTP 是一种无状态协议:HTTP 不会记住客户端会话信息,因此客户端负责存储该信息 ,以前是使用 cookie。

对于某些网站,无状态行为可能没问题,也许网站在用户会话期间不应该保留任何元素或用户操作。

但对于大多数交互式网站,cookie 是必需且必不可少的,而且我们作为网站访问者,也希望网站以某种方式运行。

非常感谢 cookie 使这一切成为可能。当客户端从 Web 服务器请求网站时,Web 服务器会响应“200 OK”,并使用设置Cookie标头。Cookie 包含会话 ID,通常还包含其他属性。Web 服务器还会跟踪网站在服务器端分发给客户端的会话 ID。

Cookie 主要用于:

  1. HTTP 会话管理
  2. 个性化
  3. 追踪

Cookies 存储在您的浏览器中。更确切地说,它们存储在硬盘上的浏览器临时目录中。存储 Cookie 的具体位置和方法取决于浏览器和操作系统。您通常通过进入设置通过浏览器界面管理 Cookie,但互联网上提供了不同操作系统和浏览器的文件夹路径。

Cookie 属性
Cookie 具有属性(有时也称为标志),这些属性非常重要,因为它们定义了 Cookie 的工作方式。以下是 Cookie 可以具有的一些属性的列表。

  • 会话 ID是一个唯一的随机字符串,用于识别和匹配客户端和 Web 服务器之间的会话
  • 过期定义 cookie 的过期日期
  • 领域指定可以使用该 cookie 的一个或多个域
  • 小路指定可以使用该 cookie 的资源或路径
  • HttpOnly启用后将阻止 JavaScript 等客户端 API 访问 cookie。这可减轻跨站点脚本 (XSS) 的威胁。
  • 安全的启用后将要求仅使用 HTTPS 发送 cookie,而不允许使用 HTTP 等未加密的连接,这使得 cookie 不易受到窃取。
  • 会议定义该 cookie 是临时 cookie,当浏览器关闭时会过期
  • 同一站点可以有严格、宽松或无值
    • 严格 = 浏览器仅向与原始域相同的目标域发送 cookie
    • Lax = 浏览器向目标域发送 cookie,即使它与原始域不同,但仅限于安全请求(如 GET),而不是第三方 cookie。
    • 无 = 允许第三方 Cookie(跨站点 Cookie)

Cookie 类型
以下是您在使用 Cookie 时可能会遇到的一些 Cookie 术语。

Cookie 可以以多种方式粗略地分为几类:

  • 有第一方 Cookie 和第三方 Cookie。
  • 有基本 Cookie(严格必要)和非基本 Cookie(非必要)。

我们将在此处使用后一种定义来对 Cookie 进行分类。分类其实并不重要,人类只是更容易将东西放在心理框架中。

此外,有些 Cookie 只是其他 Cookie 的变体。例如,您可能听说过“安全 Cookie”,但实际上它可能只是一个会话或第一方 Cookie,它具有安全的-attribute 已启用。

即便如此,会话 cookie 和第一方 cookie 也非常相似。即使在我看来术语相当模糊,并且不同的网站交替使用不同的 cookie 术语,我们仍然至少尝试对它们中的每一个给出某种定义。

必需 Cookie
基本 cookie 对于网站正常运行必不可少,并且通常可以为用户带来更便捷的浏览体验。

  • 会话 Cookie
  • 第一方 Cookie
  • 身份验证 Cookie
  • 以用户为中心的安全 Cookie
  • 用户输入的 cookies

会话 cookie (又称非持久性 cookie、内存 cookie、临时 cookie)
会话 Cookie 是临时 Cookie 文件,当用户关闭浏览器或其会话变为非活动状态(如果用户注销,会话将结束)时,这些 cookie 会被删除。它们是单会话 cookie。当用户重新启动浏览器并返回创建 cookie 的网站时,网站将无法识别用户,因为用户的浏览器中没有网站可读取的 cookie。用户必须重新登录(如果网站需要登录)。登录后,将生成一个新的会话 cookie,它将存储用户的浏览信息,并在用户离开网站并关闭浏览器之前一直有效。由​​于会话 cookie 有自己唯一的 ID,因此它还可用于跟踪网站访问者数量。如果您正在计划一次假期旅行,并且每天多次访问旅行社的网站,则 cookie 的会话 ID 将向网站显示您只是一位唯一访问者。

第一方 Cookie (又称持久性 Cookie、永久 Cookie、存储 Cookie)
第一方 Cookie 将保留在浏览器中直到用户删除它们或浏览器删除它们根据持久性 cookie 文件中包含的持续时间。这种类型的 cookie 可以用其他术语来表示,例如持久性 cookie、永久 cookie 或存储 cookie,因此它们在单个会话中具有持久性。如果在此期间未访问该网站,大多数第一方 cookie 将在 1-2 年内过期。当 cookie 过期时,浏览器将自动删除它们。第一方 cookie 最广为人知的功能是帮助用户保持其帐户登录到网站,从而避免每次访问网站时都需要重新输入凭据。

身份验证 Cookie
身份验证 Cookie是会话 Cookie 的变体。它们登录成功后将识别用户并在用户浏览授权登录用户访问的网站时携带该身份验证信息。例如,当用户通过网上银行身份验证时,他们有权查看自己的银行账户余额。如果他们转到另一个页面查看贷款,身份验证 cookie 可确保用户现在不必为该页面提供新的身份验证。

以用户为中心的安全 Cookie
以用户为中心的安全 Cookie可以跟踪身份验证错误并检测可能的身份验证滥用通过跟踪在登录页面上尝试错误登录凭据的次数。

用户输入的 cookies
用户输入的 cookies是第一方会话 Cookie,跟踪用户自己输入的操作和项目在网站上,例如填写表格或单击某些按钮(例如添加到购物车)。

非必要的 Cookie
非必要的 cookie 对于用户的浏览体验或网站正常运行而言并非必需。

  • 分析和定制 Cookie
  • 广告 Cookie
  • 第三方 Cookie
  • 超级cookie

分析和定制 Cookie
分析和自定义 cookie 会跟踪用户活动,以便网站管理员更好地了解其网站的使用情况。网站管理员可以使用分析来增强网站的一个例子是,网站上的某些信息可能确实“冷门”,这意味着用户很少打开该页面(不感兴趣)或无法找到进入该页面的方法。

广告 Cookie
广告 Cookie 仅用于定制用户在网页上看到的广告。它们使用用户的浏览历史记录使广告“更相关”。这就是为什么我们开始看到与我们之前搜索过的内容相关的广告。

第三方 Cookie(又称跟踪 Cookie)
第三方 Cookie 是坏人“cookieland” 的组成部分。这些是我们不喜欢的 cookie,也是它们声誉不佳的原因。第三方 cookie 来自用户访问的不同域,因此它们不提供会话 cookie 或第一方 cookie 的任何好处。这些 cookies 只有一个目的:追踪您。

超级cookie
从技术上讲,超级 cookie 不是 cookie,在某些情况下不会存储在用户的设备上。“普通” cookie 最多可以容纳 4 KB 的数据,而超级 cookie 可以容纳 100 KB。超级 cookie 的功能与跟踪 cookie 类似,但它们的控制方式与其他 cookie 不同。在某些情况下,会发现超级 cookie 存储在浏览器缓存中,某些形式的超级 cookie 会注入仅由 ISP 控制的 UIDH(唯一标识符标头)中。由于超级 cookie 的性质,它们更难识别,如果是 UIDH 超级 cookie,您无法清除它们。

什么是token?
token令牌是用于信息交换的独立且紧凑的 JSON 对象。典型的令牌是 JSON Web 令牌 (JWT),用于客户端(应用程序)和其他服务(如 Web 服务器)之间。详细信息取决于确切的身份验证流程。在本文中,我们将使用术语 JWT(发音为“JOT”),因为它更方便且在专业文献中被广泛使用。

与短期或长期存储用户在网络会话中的活动信息的 cookie 不同,令牌在软件之间传输信息。存储在令牌中的信息取决于令牌的类型。例如,ID 令牌携带有关经过身份验证的用户的信息。访问令牌通常包含有关安全主体及其被授权的访问权限的信息。这是 token 和 cookies 相交的地方:一些令牌存储在客户端的本地存储或 cookie 中。出于安全原因,最好存储在 HttpOnly cookie 中。我不是 Web 开发人员,但我了解到开发人员社区倾向于使用 cookie,因为本地存储被认为是不太安全的选择。还值得一提的是,令牌是协议的一部分,并非所有令牌都是同一协议的一部分。

简要解释的协议是OAuth 2.0和OpenID 连接(OIDC)

  • 开放授权是 Open Authorization 的缩写,它是一种标准,旨在处理代表用户访问资源的应用程序或网站的授权流程。简而言之,OAuth 是一种主要用于 Web 平台的授权协议。OAuth 使用访问令牌,通常但不限于 JSON Web 令牌。Microsoft Identity Platform 中的 OAuth 协议使用格式化为 JWT 的访问令牌(承载令牌)。OAuth 2.0 授权流程有多种不同类型。
  • OpenID 连接扩展了 OAuth 2.0 授权协议,使其也可用作使用 ID 令牌的身份验证协议。OpenID Connect 登录流程用于获取 ID 令牌,该令牌被发送到验证用户身份的应用程序。

令牌正在解决的问题
让我们描述一个不存在令牌的传统身份验证和授权场景。

  1. 用户首先登录,然后 Web 服务器通过从其数据库中检查输入的凭据来对用户进行身份验证。
  2. 一旦令牌匹配,服务器就会发出一个唯一的会话标识符并将其发送到客户端。
  3. 用户的客户端将会话 ID 存储在设备上。对于从客户端到服务器的每个后续请求,会话 ID 都会在 cookie 或 http 请求标头中发送。
  4. 服务器需要再次从其数据库中查找会话 ID 以识别用户并检查授权级别。

上述场景的问题在于,对于来自客户端的每个请求,服务器都需要往返数据库,这会使应用程序的使用速度变慢。

而使用令牌的场景通过发布包含用户信息和签名的 JWT 来解决后续的数据库查找问题,这些信息和签名可以验证令牌内容的真实性。

  • JWT 被发送到客户端,客户端再次存储它。
  • 对于从客户端到服务器的每个请求,客户端都包含 JWT。
  • 服务器只需要验证令牌的签名以确保其真实性,当签名被签入时,服务器可以从令牌中提取身份和授权详细信息,而无需数据库查找。

令牌类型
以下是一些常见的 token 类型:

  • ID 令牌
  • 访问令牌
  • 刷新令牌
  • Bearer 令牌

ID 令牌
ID 令牌是使用 OpenID Connect (OIDC) 登录流程获取的,该流程是去中心化身份验证的开放标准。ID 令牌必须采用 JSON Web Token 格式。它们由授权服务器 (Microsoft Entra ID) 颁发给客户端应用程序。ID 令牌包含有关用户的声明或安全主体,并可以包含有关 MFA 状态的声明。客户端应用程序可以使用 ID 令牌中的信息和声明来验证用户是否是他们声称的人。默认情况下,ID 令牌在 Microsoft Identity Platform 中有效期为一小时。ID 令牌不用于调用受保护的 API。

Microsoft 有两个版本的 ID 令牌,并且都有不同的端点。版本之间的差异在于它们可以包含的信息和声明。

  • v1.0https://login.microsoftonline.com/common/oauth2/authorize
  • v2.0https://login.microsoftonline.com/common/oauth2/v2.0/authorize

访问令牌
访问令牌是由授权服务器签名的短期(JWT)令牌,并且使客户端能够安全地调用受保护的 Web API。访问令牌不需要格式化为 JSON Web 令牌,但在 Microsoft Identity Platform 中,它们采用 JWT 格式。访问令牌包含在从客户端到服务器的每个 http 请求中。这通常通过使用“Bearer”架构的 http 请求中的 Authorization 标头来实现。这样做将避免服务器在每个请求上对用户进行身份验证的需要。客户端将访问令牌存储在 cookie 或本地存储中。与 ID 令牌一样,访问令牌也有两个版本,它们都有不同的端点。访问令牌旨在在服务器端使用。客户端不需要也不应该用来读取访问令牌的内容。

刷新令牌
刷新令牌是通常与访问令牌一起获取。它是用于获取新的访问令牌当先前的访问令牌过期时,新的刷新令牌也会过期。在 Microsoft Identity Platform 中,刷新令牌是加密的,其他人无法读取。客户端将访问令牌存储在 cookie 或本地存储中。刷新令牌的默认有效期为 90 天,单页应用除外,其默认有效期为 24 小时。

Bearer 令牌
持有者令牌是指任何拥有令牌的人都可以使用的令牌。令牌持有者无需证明自己拥有加密密钥。可以将其想象成酒店房间的钥匙卡。如果您放错了钥匙卡,而其他人拿到了它,他们就可以使用它进入酒店房间,而无需证明自己是房间的合法所有者。

JSON Web 令牌 (JWT)
JSON Web Tokens 是用于在双方之间安全地发送数据的标准化对象。为了确保 JWT 的内容在传输过程中不会被更改或篡改,JWT 使用加密密钥进行签名。这需要重复:JWT 已签名,未加密。签名验证数据的发送者,而加密将数据从纯文本转换为密文,未经授权的接收者无法读取。如果签名的令牌内容在传输过程中发生更改,公钥(用于签名令牌的私钥对)将无法再验证签名。强烈建议使用带有 JWT 的 HTTPS 等协议来保护传输过程中令牌内容的机密性。

互联网工程任务组(IETF)在RFC 7519中描述了 JWT 标准。
JSON Web Token由三部分组成:

  • 标头
  • 有效载荷
  • 签名

标头
通常,标题由两部分组成,描述代币类型和签名算法。

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

有效载荷
有效载荷是包含所有实际信息的部分

  • "iss" = 发行人声明。签发人要求确定签发 JWT 的委托人
  • "sub" = 主体声明。主体声明标识 JWT 的主体
  • "aud" = 受众声明。受众声明确定 JWT 的收件人
  • "exp" = 过期时间声明。过期声明确定 JWT 在过期时间或过期时间之后不得被接受处理的过期时间
  • "nbf" = 非之前声明。NFB 申请用于确定 JWT 不可接受处理的时间。
  • "iat" = Issued At Claim(在索赔时签发)。Issued At claim(在索赔时签发)标识 JWT 签发的时间
  • "jti" = JWT ID 索赔。JWT ID 索赔提供了 JWT 的唯一标识符

{
  "session": "ch72gsb320000udocl363eofy",
 
"client_id": "YzEzMGdoMHJnOHBiOG1ibDhyNTA=",
 
"response_type": "code",
 
"scope": "introscpect_tokens, revoke_tokens",
 
"iss": "bjhIRjM1cXpaa21zdWtISnp6ejlMbk44bTlNZjk3dXE=",
 
"sub": "YzEzMGdoMHJnOHBiOG1ibDhyNTA=",
 
"name": "John Doe",
 
"aud": "https://login.microsoftonline.com/{tid}/oauth2/v2.0/authorize",
 
"jti": "1516239022",
 
"exp": "2024-05-17T07:09:48.000+0545"
}
}

签名
标头和有效载荷都是Base64Url编码。要对令牌进行签名,需要使用编码的标头和编码的有效负载以及机密和签名算法来完成签名。

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


概括
我们了解了什么是 Cookie,以及浏览器和网站如何使用 Cookie 来增强浏览体验。我们列出了 Cookie 的一些变体及其独特特征。我们还了解了什么是令牌、JWT相关知识。