×

Token详解

前端技术网 前端技术网 发表于2023-12-23 21:35:14 浏览324 评论0

抢沙发发表评论

一、网站的token机制是什么

Token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。

简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止token泄露)。

身份认证概述

Token详解

由于HTTP是一种没有状态的协议,它并不知道是谁访问了我们的应用。这里把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下次这个客户端再发送请求时候,还得再验证一下。

通用的解决方法就是,当用户请求登录的时候,如果没有问题,在服务端生成一条记录,在这个记录里可以说明登录的用户是谁,然后把这条记录的id发送给客户端,客户端收到以后把这个id存储在cookie里,下次该用户再次向服务端发送请求的时候,可以带上这个cookie,这样服务端会验证一下cookie里的信息,看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。

以上所描述的过程就是利用session,那个id值就是sessionid。我们需要在服务端存储为用户生成的session,这些session会存储在内存,磁盘,或者数据库。

基于token机制的身份认证

使用token机制的身份验证方法,在服务器端不需要存储用户的登录记录。大概的流程:

客户端使用用户名和密码请求登录。

Token详解

服务端收到请求,验证用户名和密码。

验证成功后,服务端会生成一个token,然后把这个token发送给客户端。

客户端收到token后把它存储起来,可以放在cookie或者LocalStorage(本地存储)里。

客户端每次向服务端发送请求的时候都需要带上服务端发给的token。

服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据。

利用token机制进行登录认证,可以有以下方式:

用设备mac地址作为token

客户端:客户端在登录时获取设备的mac地址,将其作为参数传递到服务端

服务端:服务端接收到该参数后,便用一个变量来接收,同时将其作为token保存在数据库,并将该token设置到session中。客户端每次请求的时候都要统一拦截,将客户端传递的token和服务器端session中的token进行对比,相同则登录成功,不同则拒绝。

此方式客户端和服务端统一了唯一的标识,并且保证每一个设备拥有唯一的标识。缺点是服务器端需要保存mac地址;优点是客户端无需重新登录,只要登录一次以后一直可以使用,对于超时的问题由服务端进行处理。

以上就是小编对于网站的token机制的详解。

网站

二、XLNet 详解

BERT训练时将部分单词 mask起来,使模型能够利用句子双向的信息,在很多 NLU任务上取得很好的效果。但是 BERT忽略了 mask单词之间的关系,且微调过程与预训练过程不一致(微调时没有 mask的单词)。XLNet采用了 PLM(Permutation Language Model),将句子随机排列,然后用自回归的方法训练,从而获得双向信息并且可以学习 token之间的依赖关系。另外 XLNet使用了 Transformer-XL,使用了更广阔的上下文信息。

XLNet论文中首先提出了一种比较有意思的观点,将当前预训练模型分为了两类 AR(Auto Regression,自回归)和 AE(Auto Encoder,自编码器)。

GPT就是一种 AR方法,不断地使用当前得到的信息预测下一个输出(自回归)。而 BERT是一种 AE方法,将输入句子的某些单词 mask掉,然后再通过 BERT还原数据,这一过程类似去噪自编码器(Denoising AutoEncoder,DAE)。不熟悉 GPT和 BERT的童鞋可以参考前面的文章,《OpenAI GPT和 GPT2模型详解》和《彻底理解 Google BERT模型》。

AR的方法可以更好地学习 token之间的依赖关系,而 AE的方法可以更好地利用深层的双向信息。因此 XLNet希望将 AR和 AE两种方法的优点结合起来,XLNet使用了 Permutation Language Model(PLM)实现这一目的。

Permutation指排列组合的意思,XLNet将句子中的 token随机排列,然后采用 AR的方式预测末尾的几个 token。这样一来,在预测 token的时候就可以同时利用该 token双向的信息,并且能学到 token间的依赖,如下图所示。

接下来介绍 XLNet中的实现细节,其中 XLNet为了实现 PLM,提出了 Two-Stream Self-Attention和 Partial Prediction。另外 XLNet还使用了 Transformer-XL中的 Segment Recurrence Mechani**和 Relative Positional Encoding,不熟悉 Transformer-XL的童鞋可以参考前面的文章,《Transformer-XL语言模型》。

PLM(Permutation Language Model)是 XLNet的核心思想,首先将句子的 token随机排列,然后采用 AR的方式预测句子末尾的单词,这样 XLNet即可同时拥有 AE和 AR的优势。

XLNet中通过 Attention Mask实现 PLM,而无需真正修改句子 token的顺序。例如原来的句子是 [1,2,3,4],如果随机生成的序列时 [3,2,4,1],则输入到 XLNet的句子仍然是 [1,2,3,4],但是掩码需要修改成下图。

图中的掩码矩阵,红色表示不遮掩,白色表示遮掩。第 1行表示 token 1的掩码,可以看到,1是句子的最后一个 token,因此可以看到之前的所有 token(3,2,4)。3是句子的第一个 token,看不到句子的任何信息,因此第 3行都是白色的(表示遮掩)。

Two-Stream概念

XLNet打乱了句子的顺序,这时在预测的时候 token的位置信息会非常重要,同时在预测的时候也必须将 token的内容信息遮掩起来(否则输入包含了要预测的内容信息,模型就无法学到知识)。也就是说 XLNet需要看到 token的位置信息,但是又不能看到 token的内容信息,因此 XLNet采用了两个 Stream实现这一目的:

Query Stream计算

Query Stream用 g表示,Content Stream用 h表示,使用 Query Stream对要预测的位置进行预测的时候,Q(Query)向量是用 g计算得到的,包含该位置的位置信息,而 K(Key)和 V(Value)是用 h计算的,包含其他 token的内容信息。下图展示了如何通过当前层的 g计算下一层 g的过程,图中的排列是 [3,2,4,1],计算的 token是 1。

可以看到在计算 token 1的 Q向量时,只使用了 token 1的 Query Stream g,即模型只得到 token 1的位置信息。而向量 K,V使用 token 3, 2, 4进行计算,所以模型可以得到 token 3, 2, 4的内容信息。因为 token 1是排列 [3,2,4,1]的最后一位。这一个过程的掩码矩阵和上一节的是一样的,对角线上都为白色,即遮掩当前预测位置的内容信息 h。

Content Stream计算

Content Stream包含了 token的内容信息,因为 XLNet的层数很多,需要将 token的内容传递到下一层。这一层的 Q, K, V都是利用 h计算的。Content Stream的计算如下图所示。

可以看到,在计算下一层的 h1时,也会利用 token 1当前的内容信息,这样就可以将 token的内容传递到下一层,但是注意 XLNet在预测时只是用 g(Query Stream)。计算 Content Stream时候的掩码矩阵如下图所示。

和 Query Stream的掩码矩阵区别在于对角线,Content Stream不遮掩对角线,使得当前 token的信息可以传递到下一层。

Query Stream和 Content Stream组合

XLNet将 Query Stream和 Content Stream组合在一起,如下图所示。

图中最下面的一层是输入层,其中 e(x)是单词的词向量,表示输入的 Content Stream,而 w表示输入的位置信息,即 Query Stream。

XLNet将句子重新排列,然后根据排列后的顺序使用 AR方式预测,但是由于句子是随机排列的,会导致优化比较困难且收敛速度慢。因此 XLNet采用了 Partial Prediction(部分预测)的方式进行训练,对于排列后的句子,只预测句子末尾的 1/K个 token。

例如 K=4,就是只预测最后 1/4的 token。给定句子 [1,2,3,4,5,6,7,8]和一种随机排列 [2,8,3,4,5,1,7,6],则只预测 7和 6。论文中训练 XLNet-Large时使用的 K为 6,大约是预测末尾 14.3%的 token。

XLNet使用了 Transformer-XL中的 Segment Recurrence Mechani**(段循环)和 Relative Positional Encoding(相对位置编码)进行优化。

Segment Recurrence Mechani**段循环的机制会将上一段文本输出的信息保存下来,用于当前文本的计算,使模型可以拥有更广阔的上下文信息。

在引入上一段信息后,可能会有两个 token拥有相同的位置信息,例如上一段的第一个单词和当前段的第一个单词位置信息都是一样的。因此 Transformer-XL采用了 Relative Positional Encoding(相对位置编码),不使用固定的位置,而是采用单词之间的相对位置进行编码。在之前的文章《Transformer-XL语言模型》中有比较详细的介绍,感兴趣的童鞋可以参考一下。

XLNet使用了 Transformer-XL后如下图所示。 mem表示的就是前一个 XLNet段的内容信息,而 XLNet中输入的 Query Stream为 w,保存位置信息,采用的是 Relative Positional Encoding。

XLNet希望像 BERT一样采用 [A, SEP, B, SEP, CLS]的形式处理句子任务,在 BERT中有两个表征向量 EA和 EB分别表示句子 A和 B。但是 XLNet采用 Transformer-XL的段循环机制后会出现问题,两个段都有句子 A和 B,则两个句子 A属于不同的段,但是却会有相同的 Segment向量。

XLNet提出了 Relative Segment Encodings,对于每一个 attention head都添加 3个可训练的向量 s+, s-, b,然后利用以下公式计算 attention score。

其中 q就是 Query向量,这个计算得到的 attention score会加到原来的 attention score上,再计算 softmax。Relative Segment Encodings加上了一个偏置向量 b,同时 Relative Segment Encodings也可以用于一些超过两段输入句子的任务上。

XLNet的核心思想是 PLM,排列原来的句子,然后预测末尾的单词。这样可以学习到单词之间的依赖关系,而且可以利用 token前后向的信息。

XLNet PLM的实现需要用到 Two-Stream Self-Attention,包含两个 Stream,Query Stream用于预测,只包含当前位置的位置信息。而 Content Stream保存了 token的内容。

XLNet还使用了 Transformer-XL的优化方式。

XLNet: Generalized Autoregressive Pretraining for Language Understanding

三、JWT令牌详解

JWT是JSON Web Token的缩写,是一个轻巧的规范,一个开放的行业标准,它定义了一种简洁的、自包含的协议格式,这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的消息.

一个JWT实际上就是一个字符串,它由三部分组成,头部、荷载与签名

头部描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等

例如{"type":"JWT","alg":"HS256"}

其头部指明了签名算法是HS256算法

HMAC算法(非对称的)

SH256

RSA

荷载就是存放有效信息的地方

定义一个payload:{"sub":"1234567890","name":"John Doe","admin":true}

签证又由三部分组成,base64加密后的header和base64加密后的payload使用,连接组成的字符串

然后通过header中声明的加密方式进行加盐secret组合加密.

1、jwt基于json,非常方便解析

2、可以在令牌中自定义丰富的内容,易扩张

3、通过非对称加密算法以及数字签名技术,JWT防止篡改,安全性高

4、资源服务使用JWT可不依赖认证服务即可完成授权

JWT令牌较长,占存储空间比较大.

一个公钥对应一个私钥,私钥作为签名给JWT加密,那么这里需要生成与之对应的公钥:

输入密钥库口令: keytool-list-keystore changgou.jks

显示的信息为:

密钥库类型: jks

密钥库提供方: SUN

您的密钥库包含 1个条目

changgou, 2020-7-28, PrivateKeyEntry,

证书指纹(SHA1): 45:2E:51:8B:84:86:03:8C:AF:99:14:5F:4F:D6:98:33:39:92:33:79

输入命令后就可以得到公钥:

注释:classPathResource:私钥位置;

new KeyStoreKeyFactory:创建私钥工厂,需要私钥库密码和私钥位置两个参数;

keyStoreKeyFactory.getKeyPair(alias,password.toCharArray):获取keyPair对象,keyPair.getPrivate()即是获取私钥;

根据私钥获取令牌:JwtHelper.encode(JSON.toJSONString(map,new RsaSigner(rsaPrivateKey));

OK,本文到此结束,希望对大家有所帮助。