最近在做项目时用到了使用JWT生成Token,原本不是很了解JWT。就这个机会,学习了一下,并记录下来,以便以后参考。
那么什么是JWT呢?
JWT 是json web token 的简称。jwt其实就是一个字符串,主要由头部、载荷和签名三个部分组成。
类似如下字符串:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U
每个部分用英文点(.)号隔开。
头部(header)
JWT的头部位于该字符中第一部分,主要用来描述jwt的声明类型和声明加密方法的基础信息。用json形式表示如下:
{
"typ":"JWT", //表示申声明类型为JWT
"alg":"HS256" //表示声明的加密方法为HS256
}
对这个json对象进行Base64加密,即可得到JWT头部的字符串了,如下:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
载荷(payload)
载荷是JWT的核心,主要用来描述所存储用户的ID,失效时间等信息。服务端可以根据这些信息来判断改token是哪个用户已经登录的证明了。这样,服务端就可以不用保存任何信息,只要根据前段传到后端的token就可以完成登录鉴权功能。这一点与传统服务端使用session保存用户信息有本质的不同。
我们举一个简单的例子,使用json形式表示用户的ID和失效时间:
{
"uid": "110110", //用户Id
"exp": "14231234" //失效时间
}
同样经过base64加密过后得到JWT的第二部分:
eyJ1aWQiOiAiMTEwMTEwIiwiZXhwIjogIjE0MjMxMjM0In0=
签名(Signature)
签名也是一个特殊的字符串,但是它不是向前两部分一样,将某个JSON串经过Base64加密过得到的字符串。签名室友三个部分组成:
(1)经过base64加密过后的header:
base64UrlEncode(header) = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9;
(2)经过base64机密过后的payload:base64UrlEncode(payload) = eyJ1aWQiOiAiMTEwMTEwIiwiZXhwIjogIjE0MjMxMjM0In0=;
(3)secred
具体组成方式:将经过base64加密后的header与经过base64加密过后的payload用"."连接起来组成一个字符串,然后使用header中设置的加密方式(HS256),并使用secred(秘钥)进行加密,这样就得到了JWT的第三部分——签名了。
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'key'); //这里的秘钥(secret)是字符串key
最终,将这三段字符串用"."连接起来,就得到了JWT.
总结:
通过使用JWT进行认真,具有以下几点好处:
(1)首先相较于传统的session方式,JWT不需要服务端保存信息,这样减轻服务端开销,同时易于扩展;
(2)JWT能轻松实现单点登录,因为认证信息已经保存到客户端;
(3)能完成前后的分离;
(4)具有一定的安全性,这里之所以说一定的,是因为虽然JWT在载荷(payload)中使用了加密方法,但是其加密方法是能够解密的,所以依旧不能够将敏感信息保存到payload中。