初识 JWT(JSON Web Token)
官网
JWT 简单介绍
什么是 JWT
-
JSON Web Token (JWT) 是一个开放标准 ( RFC 7519 ),它定义了一种紧凑且自包含的方式,用于在各方之间作为 JSON 对象安全地传输信息。该信息可以被验证和信任,因为它是经过数字签名的。JWT 可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
-
虽然 JWT 可以加密以在各方之间提供保密,但我们将重点关注签名令牌。签名令牌可以验证其中包含的声明的完整性,而加密令牌则对其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方。
什么时候应该使用 JWT?
以下是 JSON Web Tokens 有用的一些场景:
授权:
这是使用 JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小,并且能够轻松跨不同域使用。
信息交换:
JWT是一种在各方之间安全传输信息的好的方式。因为 JWT 可以被签名——例如,使用公钥/私钥对——你可以确定发件人就是他们所说的那样。此外,由于使用标头和有效负载计算签名,因此您还可以验证内容是否未被篡改。
什么是 JWT 结构?
第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).
标题
jwt的头部承载两部分信息:
- 声明类型,这里是jwt
- 声明加密的算法 通常直接使用 HMAC SHA256
完整的头部就像下面这样的JSON:
{
"alg": "HS256",
"typ": "JWT"
}
然后,这个 JSON 被Base64Url编码以形成 JWT 的第一部分
有效载荷
令牌的第二部分是负载,其中包含声明。声明是关于实体(通常是用户)和附加数据的声明。共有三种类型的声明:注册声明、公共声明和私人声明。
注册声明 (建议但不强制使用) :
- iss: jwt签发者
- sub: jwt所面向的用户
- aud: 接收jwt的一方
- exp: jwt的过期时间,这个过期时间必须要大于签发时间
- nbf: 定义在什么时间之前,该jwt都是不可用的.
- iat: jwt的签发时间
- jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
公共声明
- 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密。
- 这些可以由使用 JWT 的人随意定义。但是为了避免冲突,它们应该在IANA JSON Web Token Registry中定义或定义为包含抗冲突命名空间的 URI。
私人声明
- 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。
- 这些都是使用它们同意并既不是当事人之间建立共享信息的自定义声明注册或公众的权利要求。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后对有效负载进行Base64Url编码以形成 JSON Web 令牌的第二部分
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
签名
- 要创建签名部分,您必须获取编码的标头、编码的有效载荷、秘密、标头中指定的算法,并对其进行签名。
jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
- header (base64后的)
- payload (base64后的)
- secret
例如,如果要使用 HMAC SHA256 算法,则签名将通过以下方式创建:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
将这三部分用.连接成一个完整的字符串,构成了最终的jwt:
eyJhbGhjsndzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
如果您想玩转 JWT 并将这些概念付诸实践,您可以使用jwt.io Debugger来解码、验证和生成 JWT
JWT如何工作?
-
在身份验证中,当用户使用其凭据成功登录时,将返回 JSON Web Token。由于令牌是凭证,因此必须非常小心以防止出现安全问题。通常,您不应将令牌保留的时间超过所需的时间。
-
由于缺乏安全性,您也不应该在浏览器存储中存储敏感的会话数据。
-
每当用户想要访问受保护的路由或资源时,用户代理应该发送 JWT,通常在使用Bearer模式的Authorization标头中。标题的内容应如下所示:
Authorization: Bearer <token>
- 在某些情况下,这可以是无状态授权机制。服务器的受保护路由将检查Authorization标头中的有效 JWT ,如果存在,则用户将被允许访问受保护的资源。如果 JWT 包含必要的数据,则可能会减少为某些操作查询数据库的需要,尽管情况并非总是如此。
- 如果令牌在Authorization标头中发送,跨源资源共享 (CORS) 不会成为问题,因为它不使用 cookie。
- 下图显示了如何获取 JWT 并将其用于访问 API 或资源:
- 应用程序或客户端向授权服务器请求授权。这是通过不同的授权流程之一执行的。例如,典型的OpenID Connect兼容 Web 应用程序将/oauth/authorize使用授权代码流通过端点。
- 当授权被授予时,授权服务器向应用程序返回一个访问令牌。
- 应用程序使用访问令牌来访问受保护的资源(如 API)。
请注意,使用签名令牌,令牌中包含的所有信息都会暴露给用户或其他方,即使他们无法更改它。这意味着您不应将秘密信息放入令牌中。
我们为什么要使用 JWT?
优点
- 因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
- 因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
- 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
- 它不需要在服务端保存会话信息, 所以它易于应用的扩展
安全相关
- 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。
- 保护好secret私钥,该私钥非常重要。
- 如果可以,请使用https协议
- 直达官网