一、定义
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Json Web Token
简称Jwt
,是一种开放标准 (RFC 7519
),它定义了一种紧凑且自包含的方式,用于在各方之间数据作为JSON
对象安全地传输信息。 数据信息经过数字签名,可以被验证和信任。 JWT
可以使用秘密(使用 HMAC
算法)或使用RSA
或 ECDSA
的公钥/私钥
对进行签名。Jwt
中签名加密解密
主要依靠加密令牌
和签名令牌
,加密令牌将信息进行加密,避免其他方知道对应声明的信息内容,签名令牌
验证加密信息中声明的完整性,当使用公钥/私钥对
对令牌进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方 。
二、结构
一个jwt
包含以下结构:
- Header
- Payload
- Signature
各个部分以点.
进行分隔,xxxx.yyyy.zzzz
。
1、Header
头部由令牌类型Jwt
以及签名使用的加密算法
类型组成,例如HMAC SHA256
或 RSA
。该部分由Base64Url方式进行编码。
{ "alg": "HS256", "typ": "JWT" }
2、Payload
负载部分,包含了声明部分,声明是对用户实体信息
以及附加数据信息
的声明,分为三种类型,registered
声明、public
声明和private
声明。
registered
声明,为一组系列规则预定义的可用的,可互操作的声明,例如iss(发行者)
、exp(到期时间)
、sub(主题)
、aud(受众)
等。声明名称仅仅三个字符,在自定义时需要注意该细节。该部分同样由Base64Url进行编码。
public
声明,为使用JWT
的人随意定义,为避免冲突,用户自定义时,应尽量避开[官方规范]https://www.iana.org/assignments/jwt/jwt.xhtml中包含的声明。
private
声明,由同意使用它们的各方之间共享信息而创建的自定义信息。
案例如下:
{ "sub":"testsub", "name":"ggcy", "iat":1516239022 }
需要注意的是,在 Header
和 Payload
中避免存放涉及到私密内容,整体信息防篡改,但是对信息并不负责,数据内容的安全性,这里是读者需要注意的地方。
3、Signature
创建指纹,需要以下几个部分,Header
、Payload
、一个秘钥
,其中 Header
和 Payload
都是需要 Base64Url
进行编码,几个部分最终由 Header
定义的加密算法进行加密。具体抽象逻辑如下:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
案例如下:
header
{ "alg": "HS256", "typ": "JWT" }
payload
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
signature
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), your-256-bit-secret ) //生成结果如下 SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
组合Jwt
,结构如下:xxx.yyy.zzz
,内容每一部分由.
,进行间隔。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
如果觉得以上内容过于枯燥,想要更具体的体会对应的各个部分的内容,可以访问Jwt
官方提供的在线Jwt
生成页面,https://jwt.io/#debugger-io,进行尝试测试。
三、工作流程
1、用户请求特定的授权链接进行认证授权,获取对应用户凭证。
2、用户凭证登录成功后,用户能够获取到一个带有 Jwt
的返回结果,获取到的 Jwt
仅仅是在有效时间内能够正常使用,操作有效时间,就将失效。
3、当用户要访问对应受到权限保护的 Api
和资源时,都需要头部带有对应有效的 Jwt
,通常在 Header
中,参数作为 Authorization
,参数内置格式为 Beaer {token}
的方式,附带到当前的请求中。
四、好处和不足
说了工作原理,那对应使用 Jwt
有什么好处?或者说有什么优缺点?
首先考虑一个问题,传统的凭证下发方式都有哪些?
简单网络令牌 (SWT
) 和安全断言标记语言令牌 (SAML
)
1、好处
1)结构上
相比Xml
,Json
的结构更加紧凑,字符串进行编码时,占用的空间更少。
2)安全上
SWT
只能由使用 HMAC
算法的共享秘密对称签名,JWT
和 SAML
令牌可以使用 X.509
证书形式的公钥/私钥对进行签名,使用 Xml
在避免引入隐藏的安全相对于 Json
是更困难的。
3)使用上
Json
解释器对于大多数编程语言来说,更加方便,能够将结构直接映射到对象上,操作上更加便捷。Jwt
中携带的公开信息,也能为跨系统交互提供一定的辅助操作。
2、不足
1)不是银弹
Jwt
并没有解决传统 Session
、 Cookie
、OIDC(OpenId Connect)
等方式的跨域和 XSS
问题。
2)依赖秘钥加密解密
Jwt
的生成和解密都需要依赖于 Secret
,常常需要以硬编码方式嵌入到系统中(或配置文件),对于秘钥的管控,影响了系统的安全性指数。
3)客户端控制缺失
一旦生成 Jwt
下发到客户端,保存在 Jwt
中的信息将对使用者来说,有效期间内,可视为透明,如果想要像 Session
那样进行远程控制异常账户,就需要使用更多的手段去弥补。
4)冗余的数据开销
本质上,对于 Session
来说,Jwt
的数据长度是比前者大的,如果不对Payload
的长度进行限制,实际长度和内容大小的优势将不复存在。
五、总结
从以上对 Jwt
的学习过程中,可以了解到,Jwt
只是一种在用户认证授权过程中,采取的一种比较简单并且防信息篡改的凭证方式,并不是事事都能估计和全面的银弹
,使用时应当依据实际情况进行选择。
六、参考链接
[1]JWT-JSON WEB TOKEN使用详解及注意事项:
https://cloud.tencent.com/developer/article/1542175
[2] Jwt 介绍