0.背景
JSON Web ( JWT ) 令牌是一种开放的、行业标准方法,用于安全地表示双方之间的声明。
在开发过程中要实现登录,授权的基础功能有很多方法,通过 JWT 来实现非常方便,安全。因为是无状态的,比较于cookie 方式的实现,JWT能很好的解决跨域请求的问题。
1. 什么是JSON Web令牌?
1.1 简介
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。此信息可以验证和信任,因为它是数字签名的。JWTs可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
1.2 签名令牌
- JWT 对 “信息” 进行签名,产生一个令牌。
- 签名的令牌可以验证其中包含的内容的完整性(防篡改)。
- 也可对“信息”加密,加密的令牌则对其他方隐藏这些内容。
- 当令牌使用公钥/私钥对签名时,签名还证明只有持有私钥的一方才是签名方。可以非对称加密方式证明了
2. 什么时候应该使用JSON Web令牌?
以下是一些JSON Web令牌很有用的场景:
2.1 授权:
这是使用JWT最常见的场景。一旦用户登录,随后的每个请求都将包括JWT,允许用户访问该令牌允许的路由、服务和资源。
单点登录(Single Sign-On)是目前广泛使用JWT的一个特性,因为它的开销很小,并且可以方便地跨域使用。
2.2 信息交换:
JSON Web令牌是一种在各方之间安全传输信息的好方法。
因为jwt可以被签名,例如,使用公钥/私钥对,您可以确保发送者是他们所说的那个人。此外,由于签名是使用“头”和“有效负载”计算的,因此您还可以验证内容是否未被篡改。
3. JWT 结构
JWT 令牌由三部分组成,这些部分由 “点” .
分隔。
- 头部(Header)
- 荷载(Payload)
- 签名(Signature)
格式:头部.有效载荷.签名
示例:xxxxx.yyyy.zzzz
下面分解来讲。
3.1 头部(header)
头部由两部分组成:
- 令牌的类型
- 正在使用的签名算法。
签名算法常见的有 HMAC,SHA256 或 RSA。
头部也用JSON描述。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,这个JSON被Base64Url
编码,形成JWT的第一部分。
3.2 有效负载(payload)
第二部分是“有效负载”,它包含了“声明(claims)”。“声明” 是指实体信息(比如用户信息)和其他扩展数据。
有三种类型的claims:
- registered claims 已注册的
- public claims 公开的
- private claims 私有的
下面分别描述
3.2.1 registered claims (已注册的声明):
这些是一组预定义的声明,它们不是强制的,而是推荐的,以提供一组有用的、可互操作的声明。比如:iss(发行者)、exp(到期时间)、sub(主题)、aud(受众)和其他。
注意,声明名称只有三个字符,比较精简。
3.2.2 public claims (公开的声明)
这些声明可以由使用JWT的用户随意定义。但是,为了避免冲突,应该在IANA JSON Web令牌注册表
中定义它们,或者将它们定义为包含防冲突命名空间的URI。
3.2.3 private claims (私有声明)
这些是为在同意使用它们的各方之间共享信息而创建的自定义声明信息。它既不是已注册声明,也不是公开声明。
例如,有效载荷可以是这样的:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后对负载进行Base64Url 编码
,这样就形成了 JWT令牌 的第二部分。
请注意,对于已签名的令牌,此信息虽然受保护不受篡改,但任何人都可以读取
。除非经过加密,否则不要将机密信息放在JWT的有效负载或头部。
3.3 签名(Signature)
第三部分是 签名。
要创建签名部分,您必须已经有了 “经过编码的头部”、“经过编码的负载”、“一个秘钥”、“在头部中指定的算法”,这样就可以进行签名了。
执行签名前准备信息:
- 经过编码的头部
- 经过编码的负载
- 一个秘钥
- 在头部中指定的算法
例如,如果要使用HMAC SHA256算法,将按以下方式创建签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名的作用:
(1) 签名用于验证消息在传输过程中没有被更改。
(2) 使用私钥签名的令牌,还可以验证JWT的发送者是它所说的发送者。
3.4 把所有的东西放在一起
要输出的内容是三个由点分隔的Base64 URL字符串。它可以在HTML和HTTP环境中轻松传递,它比XML的标准(如SAML)更加紧凑。
下面显示了一个JWT示例,它对前一个报头和有效负载进行了编码,并用一个秘钥进行了签名。
4. 怎么使用JWT
(1) 在身份验证中,当用户成功登录后,将收到一个JSON Web令牌。
由于令牌是“凭据信息”,必须非常小心地注意安全问题。一般来说,您不应该将令牌保留的时间超过所需的时间。
由于缺乏安全性,也不应将敏感会话数据存储在浏览器存储中。
(2) 当用户想要访问受保护的资源时,用户应该发送JWT。比如在HTTP请求头中携带 令牌信息,比如:
Authorization: Bearer
这可以是无状态授权机制。服务器的受保护“路由(route)”将检查信息头部中是否存在“有效的JWT”,如果存在,则允许用户访问受保护的资源。
如果JWT包含必要的数据,则可以减少查询数据库以执行某些操作的需要。
如果令牌在授权头中发送,则跨源资源共享(CORS)不会成为问题,因为它不使用cookies。
下图展示了一个经典的使用场景:
- 应用程序或客户端,向授权服务器请求授权。
- 当授权被通过时,授权服务器将向应用程序返回一个访问令牌token。
- 应用程序使用访问令牌访问受保护的资源。
请注意,使用签名的令牌,令牌中包含的所有信息都将公开给用户或其他方(虽然他们无法更改它,但可以阅读)。这意味着您不应将机密信息放入令牌中
5.为什么要使用JSON Web令牌?
JSON比XML不那么冗长,当它被编码时,它的大小也更小,使得JWT比SAML更紧凑。这使得JWT成为在HTML和HTTP环境中传递的一个很好的选择。
安全方面,使用HMAC算法,SWT只能由共享密钥对称签名。但是,JWT和SAML令牌可以使用X.509证书形式的公钥/私钥对进行签名。与签名JSON的简单性相比,使用XML数字签名来签名XML而不引入隐藏的安全漏洞是非常困难的。
JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象。相反,XML没有自然的文档到对象的映射。这使得使用JWT比使用SAML断言更容易。
在使用方面,JWT是在互联网上使用的。这突出了JSON Web令牌在多个平台(尤其是移动平台)上客户端处理的方便性。
比较编码JWT和编码SAML的长度比较编码JWT和编码SAML的长度
END