惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Hacker News
The Hacker News
S
Schneier on Security
P
Privacy & Cybersecurity Law Blog
Cisco Talos Blog
Cisco Talos Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Attack and Defense Labs
Attack and Defense Labs
NISL@THU
NISL@THU
L
LINUX DO - 最新话题
PCI Perspectives
PCI Perspectives
Cyberwarzone
Cyberwarzone
K
Kaspersky official blog
V
Vulnerabilities – Threatpost
G
GRAHAM CLULEY
Help Net Security
Help Net Security
Scott Helme
Scott Helme
V2EX - 技术
V2EX - 技术
Security Latest
Security Latest
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Hacker News: Ask HN
Hacker News: Ask HN
C
Cybersecurity and Infrastructure Security Agency CISA
O
OpenAI News
L
LINUX DO - 热门话题
T
Tor Project blog
M
MIT News - Artificial intelligence
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
Security Archives - TechRepublic
Security Archives - TechRepublic
量子位
I
InfoQ
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
SegmentFault 最新的问题
Google Online Security Blog
Google Online Security Blog
P
Proofpoint News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Application and Cybersecurity Blog
Application and Cybersecurity Blog
雷峰网
雷峰网
Cloudbric
Cloudbric
Microsoft Azure Blog
Microsoft Azure Blog
D
Docker
T
Threat Research - Cisco Blogs
Blog — PlanetScale
Blog — PlanetScale
H
Heimdal Security Blog
T
Tenable Blog
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
美团技术团队
S
Secure Thoughts
Know Your Adversary
Know Your Adversary
H
Hackread – Cybersecurity News, Data Breaches, AI and More

Ray's Blog

Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog Ray's Blog
Ray's Blog
i@mk1.io (Ra · 2022-11-15 · via Ray's Blog

详解 JWT

这可能是旧博客的最后一篇文章了,之后会使用新博客系统。

创客七户社 征文。

阅读这篇文章前,我们假定你对 HTTP 稍有一些了解。

JWT,即 JSON Web Tokens。顾名思义,其为用于 Web 授权认证的一种令牌。它最为显著的特征为安全和“无状态”。

我们先来看看过去的几种认证方式。

在 Web 授权认证这一方面,我们最先使用的是 HTTP Basic Auth。这种方式优缺点都很明显,优点是简单易用,基本上所有流行的网页浏览器都支持,开发者只需要在服务器的响应中加上一行形如 WWW-Authenticate: Basic realm="Secure Area" 的响应头即可。但这种认证方式只对用户密码进行了近乎裸奔的 Base64 编码,且易被获取造成信息泄露,甚至可以发起中间人攻击,因此极少在生产环境中使用。

Cookie/Session 认证机制是一种较为安全的 Web 授权认证机制,其分为两大组成部分,即存储在客户端的 Cookie 和服务端的 Session。它的运行方式也十分简单,客户端发出一个登录请求,服务端记录下用户信息 (即 Session),并在响应中要求客户端记录下 Cookie。在用户发起请求时,Cookie 会一同发出,服务端便可基于此进行用户认证。

这种方式看似是一种完美的解决方式,但其实仍有不足之处。

首先,Session 存储于服务端,这就必然导致服务器资源的占用。倘若有大量用户或攻击者同一时间大量发起登录请求,服务器便要大量存储 Session,容易导致内存不足,甚至崩溃。同时,如果在 Session 中置入了较大的对象,也会产生较大的性能负担。Session 的服务端开发对于程序员来说也不是一件美事,过度使用 Session 会导致代码不可读而且不好维护。

既然 Basic 不安全,Session 又会给服务器造成大量负担,那该怎么办呢?

首先我们需要一个安全的认证方式,这个好办。我们只需要一个只存在于服务器的密钥对敏感信息进行加密就可以了。

其次是不能给服务器造成性能负担,那我们势必将登录信息存储于客户端。

由此,JWT 就诞生了。

部分内容来自 https://javaguide.cn/system-design/security/jwt-intro.html

我们可以在 jwt.io 上直观感受 JWT。JWT 是一种形如 xxxxx.yyyyy.zzzzz 的由服务器返回的字符串,其中 xxxxx 为 Header (描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型)、yyyyy 为 Payload (用来存放实际需要传递的数据),zzzzz 为 Signature (签名)(服务器通过 Payload、Header 和一个密钥 (Secret) 使用 Header 里面指定的签名算法 (默认是 HMAC SHA256) 生成)。

可以看出,JWT 本质上就是一组字符串,通过 . 切分成三个经过 Base64 编码的部分。

例如:

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoic28xdmUiLCJwYXNzd29yZCI6bnVsbH0.zPEzTi2VzXpMTndG0k04QVddxaQ2Ermgw21skfyl1XWqdF5mdPoT6goQsk8XsAh40Twux-IHFl1RSYUeLuyCGQ

你可以在 这里 对它进行解码,可以得出其中包含的 Header、Payload 和 Signature。

Header 通常由两部分组成:

  • typ (type): 令牌类型,也就是 JWT。
  • alg (algorithm): 签名算法,比如 HS512。

示例:

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

JSON 形式的 Header 被转换成 Base64 编码,成为 JWT 的第一部分。

随后是 Payload。Payload 也是 JSON 格式数据,包含了 Claims(声明,包含 JWT 的相关信息)。在这里可以包含一些用户相关的信息,但请注意,默认情况下该部分并未进行加密,请不要存储隐私信息。

例如:

{
  "name": "so1ve",
  "password": null
}

这是一个很简单的例子,除了这些自定义的内容,我们还可以放置如下数据:

  • iss (issuer):JWT 签发方。
  • iat (issued at time):JWT 签发时间。
  • sub (subject):JWT 主题。
  • aud (audience):JWT 接收方。
  • exp (expiration time):JWT 的过期时间。
  • nbf (not before time):JWT 生效时间,早于该定义的时间的 JWT 不能被接受处理。
  • jti (JWT ID):JWT 唯一标识。

JSON 形式的 Payload 被转换成 Base64 编码,成为 JWT 的第二部分。

Signature 部分是对前两部分的签名,作用是防止 JWT(主要是 payload)被篡改。

这个签名的生成需要用到:

  • Header + Payload。
  • 存放在服务端的密钥(一定不要泄露出去)。
  • 签名算法。

签名的计算公式如下:

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

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用.分隔,这个字符串就是JWT

使用 JWT 进行认证,大致可以简化为如下步骤:

  1. 客户端向服务器发起登录请求(用户名、密码,或许还有验证码?),服务器后返回一个包含用户信息(Payload 中)的 JWT 令牌。
  2. 客户端将这个 JWT 存放在自己的 localStorage(本地存储)中,并且在每次需要用户信息的请求中在请求头中携带上该令牌。Authorization: Bearer <JWT>
  3. 服务器接收到 JWT,并进行解密,利用自己的密钥检验 Signature,对用户权限进行判断。如果用户拥有访问该页面的权限,则返回相应内容。
  4. 客户端接收到响应内容。

可以看出,全程服务器乐的清闲,不需要本地存储用户信息,而是将工作交给浏览器。

前面我们提到,JWT 的弊病之一是 Payload 只经过 Base64 加密 (≈裸奔了),因此不能存储隐私信息。在一般情况下,客户端无需用户的隐私信息,如果必要,我们可以采用对 JWT 进行对称加密,用时再解密的方式来增加安全性。

另外,由于 JWT 被 JavaScript 存储在 localStorage 中,由于 JavaScript 的同源策略,网站下所有的 JavaScript 代码都可以访问同一个 localStorage,从而获取到 JWT,这就会带来注入的风险。

最后,网站一定要使用 HTTPS。如果只使用 HTTP,Token 在网络中明文传输还是存在泄露的风险。

此外,Web 授权认证还有 OAuth 等方式,在此不再多说。总而言之,JWT 是目前最流行也最优秀的 Web 授权认证方案。

开学就上高中了,之后更新的频率可能会降低不少,请见谅。