- Published on
终于知道什么是JWT!
- Authors
- Name
- Joy Peng
What is JWT?
先看一下官方定义:
JSON Web Token(JWT)
是一种开放标准(RFC 7519),定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为 JSON 对象。这些信息可以被验证和信任,因为它是数字签名的。JWT 可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。
有点难懂?没关系,我们先来看一组概念:
Authorization & Authentication
authentication: the process of verifying who you are
认证是验证用户是谁的过程。通常,用户需要提供用户名和密码,然后服务器验证这些凭据是否正确。
Authorization: the process of verifying what you have access to
授权是验证用户是否有权访问某些资源的过程。通常,用户在登录后,服务器会返回一个token,这个token包含了用户的权限信息。用户在访问受保护的资源时,需要将这个token发送给服务器,服务器会验证这个token是否有效,如果有效,就允许用户访问资源。
例如,当您在机场通过安检时,您需要出示您的身份证以验证您的身份。然后,当您到达登机口时,您向空乘人员出示登机牌,以便他们授权您登机并允许进入飞机。
Session & Token
授权的方式通常有两种:session
和token
。
- Session
session的工作流程如下:
- 用户登录,服务器验证用户的用户名和密码,如果正确,服务器会创建一个
session
,session
存储在服务器端,通常是在内存中。 - 服务器返回一个
session id
,这个session id
存储在cookie中,每次用户访问受保护的资源时,浏览器会自动发送这个cookie给服务器。 - 服务器接收到请求后,会检查
session id
是否有效,如果有效,就允许用户访问资源。
优缺点:
- 服务器需要存储session,如果用户量很大,服务器的内存会很快被占满。session是存储在服务器端的,如果服务器重启,session会丢失,用户需要重新登录。 -session是存储在服务器端的,用户无法修改session,保证了安全性。
- Token
除了使用session cookie
,另一种方式是JSON web token
.
- 客户端给服务端发请求,服务端通过使用私钥加密的方式生成一个JWT token,返回给客户端。
- JWT Token存储在客户端,通常是在local storage或者cookie中。
- 每当用户想要访问受保护的路由或资源时,应发送JWT给服务端。通常在Authorization header中使用如下格式:
Authorization: Bearer <token>
- 服务器将检查
Authorization
标头中是否存在有效的JWT,验证过程如下:- 验证JWT的签名是否有效:使用公钥解密JWT,如果成功,说明JWT没有被篡改。
- 验证JWT是否过期: JWT包含了一个
exp
字段,表示JWT的过期时间,服务器会检查当前时间是否在过期时间之前。 - 验证JWT是否包含正确的权限: JWT包含了用户的权限信息,服务器会检查JWT是否包含了访问资源所需的权限。
[!Tip]
- 如果通过
HTTP
标头发送JWT
令牌,则应尽量防止它们变得太大。某些服务器不接受超过8 KB
的标头。如果尝试在JWT
令牌中嵌入太多信息(例如包含所有用户权限),则可能需要替代解决方案,例如Auth0
细粒度授权。- 如果令牌在
Authorization
Header中发送,则跨域资源共享(CORS)
不会成为问题,因为它不使用cookie
。
Structure of JWT
JSON的紧凑形式由三部分组成,用点(.
)分隔,分别是:
- Header
- Payload
- Signature
xxxxx.yyyyy.zzzzz
Header
Header是一个JSON对象,通常由两部分组成:令牌类型(即 JWT)和正在使用的签名算法(如 HMAC SHA256 或 RSA)。
Payload
也是一个json对象,其字段有三种类型
Registered claims:
JWT 规范推荐的标准化声明。
iss (issuer):签发人 exp (expiration time):过期时间 sub (subject):主题 aud (audience):受众 nbf (Not Before):生效时间 iat (Issued At):签发时间 jti (JWT ID):编号
Private claims: 这些是为在同意使用它们的各方之间共享信息而创建的自定义声明,既不是注册声明也不是公开声明。
Public claims: 可由用户定义,但应注册或使用唯一的命名空间以避免冲突。
example payload:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
Signature
要创建签名部分,您必须获取Base64Url 编码后的的
header
和payload
以及secret
并使用标头中使用的算法并对其进行签名。由于进行了签名,任何对它的篡改都会被发现。
[!Tip] JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。这就是 Base64URL 算法。
JWT的特点
- JWT十分紧凑,适合在HTTP请求的头部发送,或者作为POST参数发送。
- JWT使用的签名算法是HMAC SHA256或RSA,使用私钥签名,使用公钥验证签名。
- JWT可以跨平台使用,服务端只需要存储一个密钥,就可以验证JWT的有效性。
- JWT 的payload通常不加密,因此不要在 JWT 中加入敏感信息。为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
- JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
- JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
- JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。