• 为什么现在都流行用JWT做身份验证?
  • 发布于 2个月前
  • 216 热度
    0 评论
  • Fayer
  • 0 粉丝 39 篇博客
  •   
概述

JSON Web Token (简称JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。


JWT主要适用场景包括:
身份认证:适用较广的是在SSO场景,在客户端认证成功后,服务端签发jwt给客户端,后续客户端凭借jwt来代表自己的身份,那客户端就可以访问所有接受这套jwt签发系统的服务端(可以跨域);当前,如果jwt被泄漏,在有效期内,任何一个获得jwt的人都可以以客户端的身份和服务端合法通信
交换信息:在jwt payload中携带信息从而进行信息交换。因为jwt是有数字签名的,不可被篡改;因为payload是明文,一般在payload中不要放置敏感信息

结构
首先JWT大概长这个样子:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
结构上长这样xxxxx.yyyyy.zzzzz,用两个.划分为三个部分:分别是Header、Payload以及Signature。可以通过JWT官方提供的在线工具jwt.io/#debugger-i…进行在线解密插件(这也说明了jwt的信息都是明文的 建议不要放敏感信息)

Header
头部信息。主要包含了JWT类型以及签名算法,签名算法有HMAC SHA256、RSA、ES等系列,推荐使用ES512
{
  "alg": "HS256",
  "typ": "JWT"
}
然后再使用Base64Url编码得到第一节信息:
$ echo -n '{"alg":"HS256","typ":"JWT"}' | base64 | tr '/+' '_-' | tr -d '='
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload:
声明式信息,一般叫做claims,主要由两部分构成:
Registered claims:官方预定义的一些字段,如iss(issuer签发者)、exp(expiration time本JWT过期时间)、sub(subject主体信息)等
Private claims:应用自定义信息,在典型的SSO登录场景中,例如username、userid等信息。Payload信息是明文的,不建议放一些secret等敏感信息

上述示例中的Payload有
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
然后再使用Base64Url编码得到第二节信息:
$ echo -n '{"sub":"1234567890","name":"John Doe","iat":1516239022}' | base64 | tr '/+' '_-' | tr -d '='
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
Signature
签名是为了保证JWT是不可被篡改的,JWT一般由服务端的认证系统通过私钥统一签发,其他使用到JWT的系统可以通过对应的公钥进行验证,这背后的原理是基于非对称加密的签名算法,感兴趣的同学可以阅读下之前的文章juejin.cn/post/721633…
以HS256(HMAC+SHA256算法组合)签名算法为例,其计算逻辑如下:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

剖析

JWT流行的原因在于其无状态,具备去中心化的认证优势。回想下传统的基于session+cookie的认知方法,一是有服务端横向扩展限制,一般需要引入redis来存储这些session信息;二是在涉及跨域场景中会有问题,因为cookie的跨域限制。


JWT优势在于通过统一的认证中心签发JWT后,当用户携带这些JWT访问子资源或者其他SSO内站点时,这些服务端系统可以通过JWT签名验证客户端身份,这避免了中心化的认知流程,降低了系统间的耦合度。


但是JWT也不是非常的完美,一是一旦JWT被泄漏,拥有JWT方就能掌握你的全部认证信息,进行敏感资源操作,所以一般JWT的过期时间不宜太长;二是JWT的撤销机制比较差,一旦JWT被签发出来,由于都是基于公钥的验证机制,此时如果管理员由于泄漏风险需要撤销此JWT,单纯依赖JWT的机制是不能实现的,只能引入第三方的消息通知机制一一通知到下游系统撤销该JWT,整个过程会比较繁琐。


所以建议在极端敏感的场景下,推荐基于共享session方案实现跨域认证。实际大部分业务中,通过签发短实效性的JWT是完成能够满足安全性要求的。


应用

如果在不同后端系统间调用时需要使用JWT,其实现方案一般是每个系统维护自己的一套公私钥,并提供获取公钥方法(可以提前将公钥注册到其他系统,或者提供API以获取公钥)。


假设有A、B两系统,A需要访问B的API,则A系统提前在B系统上注册好自己的身份,并注册公钥绑定到其身份上。请求前,A利用私钥签发JWT,并包含身份信息,将JWT放置在header中和请求一起发送给B。B收到后,先从JWT中获取身份信息,并利用其身份对应的公钥验证JWT,验证通过即完成了对请求方A身份的验证


拓展
除了JWT外,常常还能看到这些名词JWS JWE,其含义如下:
JWT是一种标准,其中header中制定了签名算法,当签名算法为none时,此时的JWT也被称为非安全的JWT;反之有数据签名也被称为JWS(JWT Signature)
JWE(JSON Web Encryption)是一种对payload进行加密的方式(默认的JWT的payload是明文的),此时的JWT被称为JWE

关于JWT和Oauth2的关系:
首先JWT是一种token格式,Oauth2则是一种认证协议

JWT更加适用于API调用的场景,用于身份认证;Oauth2适用于在浏览器、移动端、PC端等需要多端共享资源或者认证的情况下使用,Oauth2的典型场景是第三方登录(如某博客网站可以利用微信账号进行登录)


总结:

JWT(JSON Web Token)是一种轻量级的身份验证协议,它具有许多优点,因此在现代应用程序中越来越受欢迎。以下是为什么现在流行使用JWT进行身份验证的一些原因:
跨语言兼容性:JWT使用JSON格式编写,这意味着它可以在不同语言和平台之间轻松传输和解析。
易于解析和验证:JWT可以使用内置于大多数编程语言中的库来解析和验证。它的结构也很简单,易于理解和解析。
无需共享状态:由于JWT不需要在服务之间共享状态,因此它是一种无状态的身份验证方法。这意味着您不需要维护会话状态,从而简化了应用程序的设计和实现。
安全性强:JWT使用加密签名来确保消息的完整性和真实性。这使得JWT很难被篡改或伪造。
轻量级:JWT不需要大型数据库查询或复杂的计算,因此它是一种轻量级的身份验证方法。这使得它在处理大量用户身份验证时非常有效。
支持多租户:JWT可以包含丰富的信息,例如用户角色、租户ID等,这使得它非常适合支持多租户应用程序。
综上所述,JWT是一种高效、安全、轻量级的身份验证方法,适用于各种类型的应用程序。


用户评论