00:00
好,我们先来简单的回顾一下访问令牌这部分的内容,访问令牌这部分呢,我们已经讲了两部分的内容了啊,第一个部分呢,是单点登录的一个知识点,然后我们对比了单一服务器模式SSO模式和token模式它们的区别以及优缺点,那我们说我们这个项目当中呢,将会采用这种脱N的模式呢,进行单点登录,接下来呢,我们又讲了JWT令牌,JWT令牌呢,首先第一个概念就是我们呢,了解到了透明令牌和自包含令牌的一个区别,那一句话来总结的话呢,透明令牌就是一个随机数,不包含呃这个必要的一些身份信息,或者是必要的,我们管它叫有效信息啊,叫claims,那么自包含令牌呢,它是啊,一个引用令牌,相当于那这种令牌呢,它是,呃,包含一些身份信息,或者是我们啊,希望存储到令牌当中的一些有效的数据信息的,那这个呢,是自透明。
01:01
临牌和自包含临牌的一个区别,接下来呢,我们就学了一个典型的自包含临牌叫做JWT啊,那JWT呢,我们重要的了解呢,就是它是如何组成的就可以了,那么从这个图当中呢,我们可以看到它由三部分组成,拍啊,令牌的头部分,Lay load载荷部分,也就是数据部分,还有这个signature签名哈希部分啊,由这三部分组成加起来就是我们完整的一个令牌了,好,那呃,接下来呢,我们来说一下啊,JWT的啊,令牌的一个生成,那刚才我们了解到令牌一共有三部分组成,对不对?那我们在开发的过程当中如何去生成这样的一个令牌呢?我们呢,一般情况下就不会啊,按照刚才他三部分的一个组成的一个方式啊,什么方式呢,其实它三部分组成的方式是这样的哈。就这种先通过这种方式计算出cdature来,通过这个,然后接下来呢,再把所有计算出来的结果啊,再给它们啊进行相加啊,怎么相加呢?其实用点相加把这串连接,最后呢,就组成了这样的一个令牌啊,那这个呢,实际上我们如果手工的去做的话,完全是可以实现的,但是未免的有些太麻烦,所以我们怎么办呢?我们会引入一些工具,呃,这些工具呢,通过非常简单的一两个啊这样的一些面向对象的方法,就能够帮助我们完成令牌的一个生成啊,另外呢,还能够帮助我们完成令牌的解析啊,以及令牌的校验啊,所以呢,我们就来熟悉一下这个JWT令牌的啊,一个基本的生成工具叫做JJWT哈啊,就基于Java的一个JWT工具哈,好,那我们呢,先创建一个项目,然后呢,在这个项目当中呢,引入。
02:52
依赖,然后呢,创建一些测试用例,来帮助我们去进一步熟悉一下这个JWT在项目当中的使用,好,我们创建一个JWT项目,我们打开我们的idea,在这个地方呢,我们新建一个project。
03:09
然后呢,还是选择普通的ma项目就可以了啊,我们点击next啊,然后呢,给这个项目呢起个名字叫做JWT,我们点击finish啊,我们在新窗口中打开这个项目。第一个步骤呢,我们先把这个依赖呢引进来,所以我们按照笔记当中的内容把这个复制一下,好,然后呢,我们来到妈面板这块刷新一下,把这个依赖呢都给它漏进来哈,Load进来之后呢,我们来看一下我们的第一个测试用例,所以首先呢,我们在原啊测试原版目录下。新建一个包吧,叫com点艾特硅谷点JWT好,然后接下来呢,我们在这面呢,新建一个Java class叫J。
04:04
WT。Test啊JWT,好,然后呢,我们在下面这块呢,先写一个test table white test和token,就是我要测一个嗯,创建JWT字符串的这样的一个啊,测试用例哈,然后那我呢,就看一看怎么去写,刚才咱们引进来一个叫呃,JWJJWT的一个依赖,是不是就这个啊啊这个依赖里面呢,它有一个工具类哈,这个工具类呢叫J。WTS啊,然后这个类里面呢,有一个静态方法叫做builder,这个builder方法呢,它可以帮助我们生成一个JWT的这么一个build,那很显然它是JWT的一个构造器哈,好,然后接下来呢,我们通过这个JWT的builder呢啊去。
05:07
呃,创建我们的这个WT,那我们要需要知道的就是我们这WT呢,有三部分构成啊,那哪三部分呢,一个是头啊,一个是载荷,一个是签名哈希,好,所以呢,我们通过这构造器呢,就分别构建JWD的头、载荷和签名哈希这几部分的内容,那么首先呢,我们设置头,设置头呢有几种方式哈,我们呢,可以看到这里面有set header parameter啊,一个建筑对一个建筑对的设计,还有呢,Set header,先生成一个header对象,然后用这个方式呢去设置头,或者是呢set header啊,就是下面这个啊,先生成一个map集合,然后把头当中需要的内容呢,用键指对放在集合当中,然后再设置这个头,用这三种方法都可以啊,我们使用第一种吧,第一种比较直观,就是设置头里面的。
06:07
间直对,那么这头呢,有两部分构成啊,我们来看一下之前咱们的这个并排的这个笔记。对头,大家看这个部分,它有两部分构成,一部分呢就是算法。一部分呢,就是类型,所以呢,我们设置的时候也要严格的按照这两部分去设置,那alg和TYP啊,所以呢,我们设置一下它的头。所以呢,这面呢,我们就a LG al LG啊,然后呢,再set parameter TY p是吧,就这两个啊,好,然后这两个分别是什么呢?我们说TYP,也就是说另一牌类型它的,呃,默认的这个,或者是说目前为止的唯一的这个名字呢,就叫JWT,因为我们现在创建的就是JWT令盘,好接下来呢,我们看前面这个alg叫算法,那么你可以选择一个算法,那现在我们这边选择的呢,是HS256,这是最常用的一个算法,所以这块呢,就是我们通过啊JWT的这个builder来设置我们的头的一个过程啊。
07:27
好,然后接下来呢,这个这个头我们设置完了之后呢,我们还啊有我看一下啊,这个没有S是不是啊好,这个头设置完成之后呢,我们还设置第二部分的内容就是载荷载荷载荷呢就是嗯,因为我们这个是一个引用签名或者是一个啊叫做自包含令牌对不对,所以呢,它这个令牌里面呢,肯定会包含一些啊额外的有效信息,那么这个额外的有效信息啊包含什么呢?比如说这个令牌呢,你要作为用户登录的一个身份识别的这么一个工具,那么你在这个令牌当中呢,就可以包含用户身份信息啊,就可以包含用户身份信息,那么我们就可以这样写点。
08:20
这个是啊,自定义信息哈。有效载荷部分的,来这边写一下,这个是头啊。然后这面呢,是载荷,载荷部分的自定义信息,好,然后那接下来呢,比如说我这载和我想包含我的昵称那个好,我还想包含我的。我还想包含我的头像,然后这个头像呢,你可以写一个具体的头像的路径啊,这边我就简单一点,我就写1.ppg,好,然后再接下来呢,我还可以包含一些等等其他的内容,比如说我还可以包含我的角色。
09:10
这些都是常见的一个自定义信息哈,所以这块是载荷部分的内容,那载荷部分除了自定义信息之外呢,还可以有一些默认的信息,好载荷默认信息包括哪些呢?它包含记得之前我们讲的吧,它包含七个主要的内容在这啊,有效载荷,然后有七个默认的字段,这七个默认的字段呢,就是这些字段了,好这些字段的话呢,我们一个一个来简单的看一下啊。比如说啊,这个第一个主题叫做sub啊,当然了,你如果自己设置的话呢,可能你就这样设置就可以了,Sub啊然后接下来呢,这面呢,就是主题,那就是嗯登,比如说上荣宝user是吧,这是我的主题,就其实这个你随便写啊,或者是啊尚荣宝用户信息对吧?啊好,那其实呢,在我们当前的这个JJWT这个工具当中呢,如果我们写默认信息的话呢,还有一种方式啊,就是因为默认信息这些字段都是固定的。
10:30
它固定就是这些字段,所以呢,他就给咱们几个固定的方法来匹配这些字段的事,那么这些固定的方法呢,包括这样的七个方法,叫site subject。你看这个subject实际上就是有给刚才咱们这个sub给sub赋值啊好。这subject实际上呢,就是给这个载荷部分的sub啊这个字段赋值的,所以呢,我们可以用它,那我们就设置一下吧,比如说我写的就是上容宝。
11:12
嗯,User啊,这个是令牌的主题,好,然后接下来呢。我再写一个叫做第二赛,还是还塞什么呢?还在第二个叫签发者,就是谁颁发的这个令牌。好叫A哈,先发者,然后呢,它实际上设置的是谁呢?就是这个ISS。这面设置的是ISS好,然后呢,这面呢,我们就。写一个签发者。
12:04
比如说我们就写艾特硅谷吧,然后接下来呢,第三个我们还可以包含什么呢?还可以包含这个,比如说接收方啊,就是商硅谷签发了,他颁发给谁把这个令牌。然后呢,这边就写site接收方的audience啊,它啊设置的就是AU啊这个属性,然后呢,所以这边呢,我们就可以写,比如说接收者也是上路好,然后再接下来呢,我们再看一看还有没有什么其他的,还有一个呢,就是这个令牌的签发时间,IA7啊先发时间,什么时候发布的这个令牌。那么就是a at,就是IA7好,然后呢,令牌的签发时间呢,比如说我们说是现在,那我就可以这样写,或者是你指定一个时间哈,令牌的先发时间,但是通常情况下,这个先发时间就是此时此刻啊,就你令牌什么时候生成的,就是什么时候签发的,然后接下来呢,还有一个叫做令牌的过期时间。
13:26
EXEXP。所以是set expiration啊,什么叫令牌的过期时间呢?大家都知道我们session是有过期时间的,对不对,然后我们往当中存数据,也可以设置过期时间啊,那这个令牌我们也有过期时间,也可以设置,你设置完了之后呢,到期了之后啊,即使之前令牌是生效的,那么只要到期了之后,这个令牌呢,就失效了,所以这个呢,我们管它叫过期时间啊,过期时间呢,我们设置一个未来的时间吧,那么未来的时间呢,是由当前的时间system。
14:06
当前时间点的current time啊,这个地方呢,是需要一个时间错的啊,所以说呢啊,就是那个需要一个时间类型的对象的啊,然后这个时间类型的对象,如果算未来的时间的话,我们是需要一个时间的,所以呢,我们就先算出一个时间戳,然后呢,New date,把这个时间戳呢复制给他,这样的话呢,在这个时间错的基础上再加上啊一个呃,这个时间这个。这个片段的一个时长对不对?好,那就是你未来的时间了,好,那这个时间抽我们怎么定义呢?比如说我定义成一个常量的to kn啊,叫做token xration b pion啊好,那么这个tokenpi呢,我我先定义在上面啊,那后面改的时候呢,比较好改,对private。
15:05
Take,然后定一个long token vaation等于那我定义的是1000,这是一秒,对吧,乘以60啊,这一分钟,然后再乘以60,这是一个小时,对吧,然后再乘以24,这多长时间,这就是一天,比如说我过期时间是一天,那你就这样定义就可以了,好,那下面这个地方呢,我们就token exp啊,把这个硬牌的过期时间大家定义一下,好,然后接下来呢,我们还有一个就是在什么之前不可用啊,我们的令牌有过期时间,也有生效时间,什么叫生效时间?比如说我现在此时此刻颁发的,但是我不想让这个令牌马上就生效,我颁发完了之后呢,我明天再生效,那你可以定义生效时间为3月2号的00:00:00啊,好,那所以呢,这个就是令牌的。
16:05
生效时间,或者说在这个时间之前,这个令牌是不可用的,叫NBF啊好,然后呢,就是点点set,叫做not before啊,所以是n BF not before,然后呢,这边呢,我们还是跟前面一样,你一个date。好,然后呢,system.current time,好,然后我让他的这个,呃,生效时间呢,稍微近一点就是。啊,1000这是1000吧,好乘以20 20秒后生效哈,就是这个令牌刚刚生成的时候呢,它实际上是无效的一个令牌,但是隔了20秒之后,你再检查的话呢,它就变成一个有效的品牌了,好那所以呢,这个是生效时间。
17:10
接下来呢,我们再来看一下,最后这个是一个安全性的一个考量,那么JWT呢,它会有一个叫做g ti的这么一个东西,是他的唯一身份识别标志,也是呢,作为啊避免请求重放攻击的,也就是说我啊生成的两个令牌,即使你前面这面是一模一样的,那么我呢,可以在这个地方呢啊用一个唯一标识来和前面的这些呢,都给它区分开啊,所以呢,就嗯通过这个吧啊来避免这个请求的一个重放攻击,实际上这个呢,你可以把它作为一个类似于UUID的这样的一个值来维护啊,啊就是或者是一个随机数,或者是一个UUID啊总之呢,它可以啊避免我们的这个啊重什么叫请求重放,就是有的人拿着你这个令牌,一模一样的令牌,然后呢,去发起一个啊,向服务器发起一个这个请求。
18:10
那你会发现啊,如果别人盗取你的令牌,拿着一模一样的令牌向服务器发起请求的时候。那么这个。这个就是请求十有八九就会成功,对吧,为什么?因为你作为一个合法的用户,你发起的请求成功了,那么一个非法的用户,一个恶意的用户,他有你相同的这样的一个呃令牌去向服务器发起请求,那令牌的呃所在的那个服务器啊,呃就是这个校验令牌的这个服务器,如果校验规则一致的话,那一定会校验成功啊,就像啊,你去银行,你输入那个银行卡的密码,你的密码是123456,如果被别人盗取的话,也是123456,这不就把你的钱取出去了嘛,对不对,是一个道理,所以如果你的令牌呢,泄露出去了,别人拿走了,那么就会啊,很容易的去盗取你的个人信息,或者是呢啊,用你的身份去做一些非法的事情,那我们如何避免呢?
19:09
如何避免这种事情,那在一般情况下,在这个,呃,就是比如说。呃,我们在网上转账的时候,那他有的时候有些银行他除了需要你的一个呃这个取款密码之外,他是不是还给你发一个验证码啊是吧?给你手机上发一个验证码,然后你要同时输入这个取款密码和这个随机的验证码,这样的话呢,才能够把这个呃钱取出来,或者说这样的话呢,银行那边呢,才能校验通过啊,所以说呢,它这个里面是一定要有一个随机的验证码进行一个临时校验的,否则的话呢,他就没有办法啊,知道你这个请求呢,是一个合法的请求,而不是有人盗了你的密码来向我这面呢去发起一个取款请求,对吧?啊,然后这个j wi,这个j ti也是一样的,你可以把它理解为一个临时的验证码啊,那这样的话呢,即使有人窃取了你啊JWT的一个令牌,那么如果他连验证码也给你窃取过去的话,那就意味着。
20:17
档次生成的这个随机数居然是一模一样的,那这个是不是就不可能啊?明白我的意思吗?然后再说一遍啊,就是我们来发送一个请求的时候啊,最后这一个部分的内容呢,它是随机生成的,动态生成的,如果最后这一个部分的内容呢,它两次是一模一样的。那么有没有可能呢?就可能性非常小,对不对,所以呢,就说明这是一个请求重放攻击,什么叫请求重放,就是他窃取了你的JWT字符串,然后呢,用一模一样的字符串又一次的向服务器发起了请求,那么服务器呢,就会识别出这两次请求呢,居然是一模一样的,这两个JWT串呢,居然是一模一样的,那么它呢,就会拒绝这个第二次一样的请求,所以这块呢,就是我们所说的如何避免请求重放攻击啊,那当然了,这种重放攻击一般情况下,如果我们服务器端做的话呢,还要结合一个过期时间,就是你的那个过期时间呢,不要弄得太长啊,因为长时间看来的话,时间越长,它这个随机串重复啊,出现冲突,发生碰撞,什么叫发生碰撞,就是一致了,发生碰撞的可能性就更大一些,所以呢,在短时间内啊,那我们呢,认为这个随机数呢,它发生碰撞的可能呢。
21:39
就比较小啊,甚至是没有是吧,无限区域于零,所以呢,我们就可以使用这个呢,来去避免请求通胀攻击啊好,所以这个呢是我们的GT。然后这个在用的时候,大家知道它是做什么的就可以了,然后所以呢,我们在这个地方呢,点点。
22:03
啊,那个g ti呢,它是用这个ID啊来,呃,这个表示的那ID大家都知道identify对吧,就叫唯一标识嘛,所以说每一次生成的那都不一样就可以了,那在这个地方呢,比如说我们用UUID来表示UU id.random u u id.to string,好这样的话呢,我们就每一次生成JWT的时候呢,都有一个唯一的标识啊好,然后接下来呢,在这面呢,啊,我们就到这为止,12345677个JWT的默认信息,以及若干JWT的自定义信息啊作为JWT3个部分的第二个部分,载荷部分我们就定义完了,然后接下来呢,我们再定义最后一部分叫签名哈希。好,签名哈希这块呢,我们有一个方法就是sign with啊叫签名啊,用谁来签名呢?首先我们要定义签名的这样的一个算法,那么这面呢,我们用这个,嗯。
23:18
HS256,就是你这个算法呢,要和前面你定义的头当中的这个算法保持一致啊,然后接下来呢,就是我们呢,有一个啊,就相当于密钥似的啊,就设置一个密钥,密钥的话呢,我们可以在上面设置一下private。死哉。Static,然后呢是string tokenig哈,然后呢是K,然后等于比如说我们写艾特硅谷123啊,当然这个东西你设置的越长越复杂越好啊,我们就先简单的这样设置一下,然后呢,在这面呢,我们就把这个密钥写回来,所以呢,根据这个HS256算法啊,携带着这个密钥,我们呢生成一个签名,当然整个生成签名的过程它是相对比较复杂的,他要把前面你设置的这些基本信息呢,都要参与到签名的运算当中,最后呢才生生成一个签名哈,好。
24:22
然后我们这个签名生成完了之后呢,我们最后组装JWT怎么组装呢?它有一个方法叫做compact,就是把所有的部分连接起来啊,我们说我们JWT呢,最后组成呢,就是把所有的部分呢,给它用点连接起来,对吧?啊好,所以这样的一个过程,所以是compact啊。好,那这样的话呢,整个这个过程呢,我们就得到了一个JWT字符串。
25:07
好,然后接下来呢,我们可以把这个JWT呢给他打印一下。那接下来呢,我们来运行一下这一单吧。好,大家看这样的话呢,我们就生成了一个字符串,这个就是很典型的一个JWT字符串了,在这个字符串当中呢,我们有这样几部分的内容,首先前面这部分是由DWT头生成的啊,然后紧接着是一个点对吧,然后连接中间这部分载荷的部分啊,所有中间这部分一直到这啊。都是载荷部分好,然后再加上一个点,后面这块呢,是签名哈希部分啊,所以他们三个组装起来,拼接起来,就构成了我们的这个JWT组船。
我来说两句