什么是JWT
JSON Web Token (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间以 JSON 对象的形式安全地传输信息。此信息可以验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。
简单来说,JWT就是用来判断某种信息是否可以被信任的一种签名json
JWT使用场景
1. 身份验证(Authentication):JWT 可以被用作用户登录的身份验证凭证。当用户成功登录后,服务端可以生成一个包含用户信息的 JWT,并将其返回给客户端。以后,客户端在每次请求时都会携带这个 JWT,服务端通过验证 JWT 的签名来确认用户的身份。
2. 授权(Authorization):在用户登录后,服务端可以生成包含用户角色、权限等信息的 JWT,并在用户每次请求时进行验证。通过解析 JWT 中的声明信息,服务端可以判断用户是否有权限执行特定的操作或访问特定的资源。
3. 信息交换(Information Exchange):由于 JWT 的声明信息可以被加密,因此可以安全地在用户和服务器之间传递信息。这在分布式系统中非常有用,因为可以确保信息在各个环节中的安全传递。
4. 单点登录(Single Sign-On):JWT 可以被用于支持单点登录,使得用户在多个应用之间只需要登录一次即可使用多个应用,从而提高用户体验。
JWT优势
无状态:JWT 的验证是基于密钥的,因此它不需要在服务端存储用户信息。这使得 JWT 可以作为一种无状态的身份认证机制。
跨语言支持:JWT 的标准化和简单性质使得它可以在多种语言和平台之间使用。
安全性高:由于 JWT 的载荷可以进行加密处理,因此 JWT 能够保证数据的安全传输。同时,JWT 的签名机制也能够保证数据的完整性和真实性。
为什么需要JWT
在一些web项目中,使用Cookie-Session
模式实现用户认证的相关流程大致如下:
- 用户在浏览器端填写用户名和密码,并发送给服务端
- 服务端对用户名和密码校验通过后会生成一份保存当前用户相关信息的session数据和一个与之对应的标识(通常称为session_id)
- 服务端返回响应时将上一步的session_id写入用户浏览器的Cookie
- 后续用户来自该浏览器的每次请求都会自动携带包含session_id的Cookie
- 服务端通过请求中的session_id就能找到之前保存的该用户那份session数据,从而获取该用户的相关信息。
这种方案依赖于客户端(浏览器)保存 Cookie,并且需要在服务端存储用户的session数据。
在移动互联网时代,用户可能使用浏览器也可能使用APP来访问服务器,我们的web应用可能是前后端分开部署在不同的端口,有时候我们还需要支持第三方登录,这下Cookie-Session
的模式就有些力不从心了。
JWT就是一种基于Token的轻量级认证模式,服务端认证通过后,会生成一个JSON对象,经过签名后得到一个Token(令牌)再发回给用户,用户后续请求只需要带上这个Token,服务端解密之后就能获取该用户的相关信息了。
JWT的结构
JWT由三部分组成,使用.
分隔,他们是:
- Header(头部)
- Payload(载荷)
- Signature(签名)
Header
JWT头部通常由两部分组成:令牌的类型(JWT)和正在使用的签名算法,例如 HMAC SHA256 或 RSA。
json
{
"alg": "HS256",
"typ": "JWT"
}
然后,JSON 数据经过 Base64Url 编码以形成 JWT 的第一部分。
Payload
JWT 的载荷也称为声明信息,包含了一些有关实体(通常是用户)的信息以及其他元数据。有三种类型的声明:已注册 、公共 和私有声明。
- **已注册的声明(Registered Claims):**这些是一组预定义的声明,不是强制性的,但建议使用,以提供一组有用的、可互操作的声明。包括 iss(发行者)、sub(主题)、aud(受众)、exp(过期时间)、nbf(生效时间)、iat(发布时间)和 jti(JWT ID)等。
注意:声明名称只有三个字符长,因为JWT是紧凑的
-
**公共声明(Public claims):**这些声明可以由使用 JWT 的用户随意定义。但为避免冲突,应在 IANA JSON Web 令牌注册表中定义它们,或将其定义为包含抗冲突命名空间的 URI。
-
**私有声明(Private Claims):**这些声明是保留给特定的应用程序使用的,不会与其他应用程序冲突。
示例有效负载:
json
{
"sub": "123456789",
"name": "John",
"admin": true
}
注意:注意,对于签名令牌,此信息虽然可以防止篡改,但任何人都可以读取。除非 JWT 已加密,否则不要将机密信息放在 JWT 的 payload 或 header 元素中。
对有效负载进行 Base64Url 编码,以形成 JSON Web 令牌的第二部分。
Signature
JWT 的签名是由头部、载荷和密钥共同生成的。它用于验证 JWT 的真实性和完整性。一般情况下,签名也会采用 Base64 编码。
例如,如果要使用 HMAC SHA256 算法,将按以下方式创建签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证消息在整个过程中没有被更改,并且在使用私钥签名的令牌的情况下,它还可以验证 JWT 的发件人是否是它所声称的身份。