阅读 4752

jwt生成的token,应该存在哪里?

答:通常存储在客户端里。

jwt 即 JSON Web Token,是一种认证协议,一般用来校验请求的身份信息和身份权限。

早上逛某乎的时候,遇到一位同学在问这个问题,很好奇jwt的存储位置。刚好前段时间在学习此内容,不请自邀,厚颜强答。

最开始我也很好奇这个token怎么保存,还差点想搞个redis存储这个token。

后来查阅资料才知道,原来这个token,服务端是可以不保存的。只需要客户端保存好就行,无论什么保持方式,甚至你让用户写纸条揣兜里都可以!

那这个token是怎么工作的呢?

先来说说需要服务端存储的操作,即传统的session会话的做法。

首先要做用户登陆,先要在服务端维护一个登陆表,这个登陆表可以放在缓存里,也可以放进数据库里。

当用户登陆的时候,把用户信息写入这个登陆表,然后导出一个登陆id,也就是所谓的session,把这个session返回给客户的,让客户端下次请求把这个信息带上来。

对于前端的小伙伴来说,这个过程通常无感知,后端的老哥们使用一个叫set-cookie的http头字段,自己把数据写入浏览器cookie里了。然后请求的时候,浏览器又会自己把cookie写进请求头里面。

当客户端请求进入服务端时,服务端拿到cookie里面的session,然后到登陆表里面去查用户信息,校验用户权限,然后即可完成正常的业务交互。

诶,那现在我因为各种乱七八糟的原因,不想维护一个登录表了,想想要怎么搞?

简单呀,直接把用户信息发给客户端,让客户端每次把用户信息都带过来,这样请求一进来,连表都不用查,直接就知道是哪个用户在请求。

但是这样子,用户的信息都曝光了,那些中间人呀,最喜欢这种耿直请求了,他们直接拿个凳子坐在你服务器端口,坐个几天,你数据库里的全家老表就被别人扒个清清楚楚。

这样肯定不行,那怎么办?

加个密再混个淆呗,这样老哥们拿到你的token,一时半会也一脸懵逼,大概率会大大咧咧地走了,只留下少部分有备(KPI)而来的老哥在苦苦寻求破解。

而你在服务端一解密,你就拿到用户信息了,同样的,你把过期时间也写进密文里面,遇到过期就401跳登录页。这样,一个不需要后端存储登录凭证的方案就出炉咯。

这就是jwt最基本的工作原理:就是把身份信息交给客户端保管。

jwt生成的token由header、payload、signature三部分组成,这三个部分用小数点“.”分隔开。

  • header,也就是头部信息,是描述这个token基本信息,是一个json格式:
    {
        "alg":"HS256",
        "typ":"JWT"
    }
    复制代码
    alg代表的是后面signature签名部分的生成加密算法,typ表示该token是jwt类型。
  • payload,就是你的那些用户数据啦,也是一个json格式。不过jwt不建议将敏感数据放进里面,因为规范里,payload和header一样,仅仅只是做一次base64编码后显示在token上。
  • signature,是这个token的签名,通常情况下是将前面的header和payload加上一个你自己定义的私钥字符串一起加密生成的字符串。

因为前面说了,jwt仅仅是将payload的内容做一次base64编码,所以那些攻击者老哥要改你的内容还是很简单的,但是老哥们不知道你的私钥啊,改了之后没法生成正确的签名,用加密的方式再次对请求进来的header.payload进行校验,发现跟signature对不上,这时候你就可以很清楚知道,有人在搞事情,直接返回个500假装服务器挂了。

如果想更安全,建议全程使用https协议进行请求通信。

当然,你已经了解了这个工作原理,自己搞一套恶心人的规范,也不是不行,比如,把payload再加一次密然后gzip下等等。

那,采用jwt的好处都有啥?

第一点,自然是服务端不需要维护一个登陆表了,节省空间,特别是用户多的情况。

第二点,拓展简单,前提是你不搞事情,老老实实遵守采用json格式去表述你的内容。

第三点,无状态,只要服务端支持解析,就可以开展业务,不需要专门搞个机制去共享session,方便加机子。

第四点,支持各种各样的客户端,不支持cookie也能玩。

坏处嘛,自然就是每次请求都要把这些数据带来带去的,肯定是增加了请求内容的。而且,每次请求进来你都要去校验,去拿header和paylaod加一次密与signature校验,也会增加请求的处理时间。这个与传统操作相比,其实是一个时间与空间之间的权衡问题,最后,还是看你选择咯。

文章分类
后端
文章标签