OAuth 2.0 实战课
王新栋
京东资深架构师
16397 人已学习
新⼈⾸单¥29
登录后,你可以任选2讲全文学习
课程目录
已完结/共 17 讲
开篇词 (1讲)
OAuth 2.0 实战课
15
15
1.0x
00:00/00:00
登录|注册

04 | 在OAuth 2.0中,如何使用JWT结构化令牌?

你好,我是王新栋。
在上一讲,我们讲到了授权服务的核心就是颁发访问令牌,而 OAuth 2.0 规范并没有约束访问令牌内容的生成规则,只要符合唯一性、不连续性、不可猜性就够了。这就意味着,我们可以灵活选择令牌的形式,既可以是没有内部结构且不包含任何信息含义的随机字符串,也可以是具有内部结构且包含有信息含义的字符串。
随机字符串这样的方式我就不再介绍了,之前课程中我们生成令牌的方式都是默认一个随机字符串。而在结构化令牌这方面,目前用得最多的就是 JWT 令牌了。
接下来,我就要和你详细讲讲,JWT 是什么、原理是怎样的、优势是什么,以及怎么使用,同时我还会讲到令牌生命周期的问题。

JWT 结构化令牌

关于什么是 JWT,官方定义是这样描述的:
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。
这个定义是不是很费解?我们简单理解下,JWT 就是用一种结构化封装的方式来生成 token 的技术。结构化后的 token 可以被赋予非常丰富的含义,这也是它与原先毫无意义的、随机的字符串形式 token 的最大区别。
结构化之后,令牌本身就可以被“塞进”一些有用的信息,比如小明为小兔软件进行了授权的信息、授权的范围信息等。或者,你可以形象地将其理解为这是一种“自编码”的能力,而这些恰恰是无结构化令牌所不具备的。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

在OAuth 2.0中,使用JWT结构化令牌是一种高效且安全的方式。JWT(JSON Web Token)是一种紧凑的、自包含的方式,用于在各方之间安全地传输信息。它由头部、数据体和签名三部分组成,可以携带丰富的含义,与原先随机字符串形式的令牌有着明显区别。JWT令牌在授权服务流程中的应用,使得受保护资源服务无需再依赖数据库或RPC服务,而是直接解析令牌本身所包含的信息,实现了令牌内检。文章还介绍了使用开源工具JJWT在Java中生成和解析JWT令牌的方法,强调了JWT的优势和安全性。通过对JWT令牌的详细解释和实际应用,读者能够深入了解JWT的结构和使用方式,以及其在OAuth 2.0授权流程中的重要性。 JWT令牌的优势包括用计算代替存储,加密传输保障安全性,以及增强系统的可用性和可伸缩性。然而,JWT令牌也存在“覆水难收”的问题,即无法在使用过程中修改令牌状态。为了解决这一问题,文章提出了两种解决方案:将秘钥粒度缩小到用户级别或将用户密码作为JWT的密钥。 此外,文章还介绍了令牌的生命周期管理,包括令牌的自然过期过程、刷新令牌请求新的访问令牌以及第三方软件主动发起令牌失效请求等情况。 总的来说,本文深入探讨了JWT令牌在OAuth 2.0中的应用和优势,同时也指出了其存在的问题和解决方案。读者通过阅读本文可以全面了解JWT令牌的结构、优势、安全性以及在授权流程中的重要性,为实际应用提供了有益的指导和建议。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《OAuth 2.0 实战课》
新⼈⾸单¥29
立即购买
登录 后留言

全部留言(55)

  • 最新
  • 精选
  • Neo
    老师,您好,有2个疑问: 1. 在jwt.io网站上验证的时候,如果不输入密钥,返回invalid Signature, 但是header和payload信息依然可以正确显示。我的理解是,在生成header和payload部分的时候,是通过base64编码,没有进行加密处理。最后的签名是保证整个body在传输的过程中没有被篡改。那么是不是意味着使用JWT方式,信息的主体还是依然能被未授信的第三方获取到? 2. 您提到JWT的一个优势是资源服务器不需要依赖数据库存储相关的信息,从而易于横向扩容。但是密钥部分还是躲不过需要查询的,可能依然需要存储。另外,如果采取一个用户用一个密钥的方式,资源服务器如何知道某个JWT token是给哪个用户使用的?(用户信息包含在header or payload中?) 谢谢

    作者回复: 1、JWT肯定要加密传输,这点我们文中强调了,不做加密的结果就是你说的,加密用对称和非对称都可以,看实际需要,追求性能就是对称,可通过管理秘钥来对冲掉对称带来的相比非对称的弱化的那部分安全。 2、是的,用生成秘钥的方法,这是管理我们扔出去的JWT TOKEN的方式之一,如果只靠有效期当然也可以,但如果追求更进一步管理的话就需要做点额外的消耗。如果通过秘钥来管理,就需要一个秘钥管理系统,另外JWT肯定是要加密处理,而且加解密的重点不在于加解密算法,而在于秘钥管理,需要我们要把秘钥生成在独立于授权系统之外的秘钥管理系统里面,存储关系就是app_id+用户=秘钥,这里的用户就是TOKEN换取出来的。

    2020-07-07
    5
    26
  • 刘丹
    我对JWT的理解是:JWT本身只对payload进行了签名,并没有做加密(base64编码不算加密)。文中多次提到加密,我比较疑惑,是我的理解错了吗?

    作者回复: 你理解是对的,签名是签名,加密是加密。 通过阅读官网上的下面这段话,可以帮助理解,在官网上有这么一段话: “Signature To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. For example if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way:” 意思是,用SHA256加密算法进行签名。 像我们熟知的MD5,SHA-0,SHA-1都是签名的算法,但也都都是计算机密码学中的最经典的加密算法,由于对MD5、SHA-0和SHA-1出现过成功的碰撞破解,现在已升级更新成SHA-2、SHA-3,而SHA256属于SHA-2。 签名实际上是一个加密的过程。在我们给的例子中使用了JJWT这个三方工具库,它的内部帮我们实现了签名和加密的工作以及包括验证签名的工作。 我们例子中给的是HS256算法,因为对称比非对称效率高些,但同时我们又做到了用户粒度的秘钥控制,来抵消对称不如非对称的那部分安全性,所以我们采用了对称的算法。

    2020-07-10
    4
    14
  • Geek_7932
    老师,感觉JWT在文章中的讲解在加密、解密这一块稍微有点模糊,不易理解 JWT在这里的作用主要是将用户授权信息保存在结构体中,生成和内容校验都是在授权服务和受保护资源这一方 对于第三方应用来说,JWT和UUID的token都是一样的,就是个授权字符串;而对于授权服务这方来说,是不太一样的,JWT上存用户授权信息,而UUID则是在数据库存授权信息 对于JWT是否使用对称和非对称加密,密钥/(公钥、私钥)都只是授权服务/受保护资源这一方用到了,选择哪种加密方式其实在这差别不大,密钥/(公钥、私钥)都不会公开出去,而且对称加密还有速度更快的优势,或许对称加密在这更加合适

    作者回复: 你的理解是对的

    2020-08-10
    3
    11
  • stg609
    另外,文中提到的两种方式来让JWT失效,我觉得并不一定可行,这两种方式有效的前提应该是资源服务器每次验证jwt的时候都会先去授权服务器要一遍秘钥,这样才能通过秘钥的变更来导致jwt失效。 但很多时候,为了进一步发挥jwt的去中心化优势,资源服务器在获取秘钥后通常会进行缓存,后续的请求并不会再去获取秘钥,这样即使更改秘钥也无济于事。除非同时重启资源服务器。 还是推荐让jwt不要保存敏感数据,同时让有效期尽可能短,比如 15 分钟,来减少风险。 如果实在安全性要求高,就弃用jwt这种格式。

    作者回复: 尽量时间短也是非常重要的,这也是我们使用JWT的一个原则之一。 在这个时间短的范围内,如果也想让jWT失效,我们势必要做点什么,比如我们说的”粒度秘钥“。 架构中的成本从来不会消失只会转移,让能胜任的”中间件“接收这个成本,那是它擅长的事情。 更新密钥的时候一起更新缓存就可以了。

    2020-08-14
    8
  • stg609
    讲的很精彩,但是似乎少了一部分,就是服务端到底是如何来验证一个jwt是否合法的?

    作者回复: 多谢肯定,咱们文中有介绍到,”使用 JJWT 解析 JWT 令牌时包含了验证签名的动作,如果签名不正确就会抛出异常信息。我们可以借助这一点来对签名做校验,从而判断是否是一个没有被伪造过的、合法的 JWT 令牌。“

    2020-08-14
    2
    5
  • 赵嘚住
    老师,您好,还有个问题,既然说了减少和数据库的调用次数,那jwt的第三部分秘钥如果验证他的准确性?这个秘钥不也是要存储在数据库,当接受到token解密以后,通过信息在数据库中查出来对比以后才能验证通过,或者rpc以后验证?这样总还是要查询数据的,只是没有暴露密码而已,但很多问题还是没有解决?求老师解答

    作者回复: 减少数据库查询次数是相对于普通的token来说的,普通的token是一个无意义的随机的字符串,需要再次匹配数据库拿到更多的用户信息,比如哪个用户给哪个应用授权了。结构化JWT令牌自包含了这些信息,所以不需要额外的查询数据库。 但是,我们需要对JWT令牌数据进行加密,这就引出另外一个加密的问题,在回答其他同学的时候也提到了这点,加密的重点是秘钥管理,这已经是超出了JWT的范围了,JWT设计的时候它关注的是结构化,所以对于加密这套系统的设计就需要额外的考虑。 我们是一定要能够做到对扔出去的JWT令牌做到可控的,也就涉及到更细粒度的秘钥管理,这时,可以采用redis这样的分布式缓存或者本机缓存来解决查询秘钥更新的问题,用普通的mysql做持久化,更新的时候更新到redis或者本地缓存的数据。

    2020-07-08
    4
  • 蓝魔丶
    老师,jwt中signature已经在签名的时候用到了一个secret,这样已经能保证只有知道secret的第三个方才能验证jwt合法性,为什么还要加密,为了防止解密出head和payload?

    作者回复: 是的,为了防止解密出payload。在将JWT用作【访问令牌】的时候,令牌的内容第三方应用也是不能被允许知道的,对于第三方应用来讲【访问令牌】对它不透明。 不过当我们讲到09的时候,通过OAuth 2.0 来实现一个用户身份认证的时候会用到【ID令牌】,这个【ID令牌】允许被第三方软件解析,因为这种情况需要一个用户标识。

    2020-07-13
    3
    3
  • 哈德韦
    如果需要从服务器端直接暴力将某些用户“踢出下线”,是不是就不能使用 JWT 令牌?除非在另外的密钥管理系统里,将这些用户的密钥强行改掉?

    作者回复: 可以使用JWT令牌,为了解决“覆水难收”的问题,需要额外的成本来处理,就是管理那个秘钥。就类似你说的“强行改掉”,这样当JWT请求到平台的服务端的时候就验证不通过了,也就是类似你说的“踢出下线”。

    2020-07-13
    3
  • 约书亚
    请问一个用户一个密钥这种方案用的多么。 我感觉无论怎么设计,受保护资源都要存储额外存储一些信息才行,这样JWT的优势就没了。 既然这样我们为什么不用一个随机生成的token代替JWT,让受保护资源通过调用授权服务的接口来验证token以及权限呢? 确实这JWT方案可以减少对授权服务的请求,但还多了同步密钥信息的功能,如果有多个资源服务需要验证token,那是不是密钥信息要冗余多处,增加了泄漏的风险?

    作者回复: 如果要做到细粒度的安全控制,肯定是要缩小到一个用户一个秘钥的粒度。 秘钥信息的管理涉及到额外的一套秘钥管理系统。

    2020-07-08
    2
    3
  • 老烟斗
    把用户密码当做秘钥不合适吧,如果用户修改密码,所有的授权都会失效

    作者回复: 用户修改密码,这个动作本身在安全背后是一件很严密的事情,对授权系统来讲,它接收到的事件,就是密码修改了,它的反应一定要让授权失效,因为授权系统不知道谁修改了密码。

    2020-07-27
    2
    2
收起评论
显示
设置
留言
55
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部