jwt安全上路

1,145 阅读4分钟

jwt是把用户的身份信息加密后存在客户端,可以代替session机制,服务端不需要保存用户状态。但是jwt的不能防盗用。

如何防止盗用呢?

  • jwt的令牌不要存在localstorage,因为这能通过js获取,而应该放在httpOnly的cookie中。但是cookie有大小限制,因此token不能放太多信息。
  • 使用https避免中间人劫持。粗略理解一下,两个关键点,1非对称加密:即你用公钥加密的消息,在这个世界上只有唯一的私钥才能解密;2信任公钥:通过可信任的浏览器内置证书,校验服务器的ssl证书,从而信任传递过来的公钥。只要这两点达成,那你发的消息,就的的确确在这个世界上只有那个服务器的私钥能解密。那就算黑客把你网线拔了,也顶多是使你不能上网而已,他并不能盗用你的身份。当然,实现上述要求并不容易,这个过程是一个很长的信任链,任何一个环节都不能出错。

jwt的header和payload仅仅被base64加密,相当于明文传输

  • jwt的token有三部分,header、payload、signature。生成jwt的时候,确实设置了一个secret,但是,这个secret是给生成签名的hash算法用的。也就是说,signature保证header、payload没有被篡改,但也仅此而已

jwt的劣势

  • 服务端无法管理用户状态,这是优势,也是劣势。劣势如无法主动注销用户,即无法注销token。比如用户在另一个设备修改了密码,但是旧设备在token没过期,就仍能够免登录,就因为你无法定向注销token,而人家这个账号还有10台设备的token需要注销。当然,你可以搞一个token服务器,每一份发出去的token都在服务器端也存一份以供管理,但是,这样跟把用户session状态存到redis的方式就没什么区别了,所以又为什么要用jwt呢。

jwt的token如果真的被盗用了呢

  • 说结论,如果token被盗用了,其实你只能躺平。因此,应当把这个问题转化为,jwt适合什么场景?即响应给用户的内容,具有时效性,并且身份标识(由token携带)无法被修改,并且将来对此身份标记的应答,没有安全问题。

最后说说我个人的疑问

payload为什么不加密呢?这说明了jwt原本就不适合用来存放敏感的用户信息,jwt的token就只适合存放一个公开透明的用户身份,就算全世界都知道都无所谓。

可能有的小朋友要问了,老师,如果我就加密payload呢?我猜,还是上面那个原因,token设计出来就不是让你存敏感信息的,你想加密payload,那就自己加密吧,反正jwt是没有帮你做的。

可能有的小朋友又要问了,老师,我在发token的时候,能不能随机选择一些用户网络信息来加入payload再加密一下,这样不就能防盗用了?比如ip信息。这样每次拿到token解密再对比一下,因为payload是加密过的,客户端也不知道我用了ip作为身份校验,也许我还用了别的呢。我猜,这种做法更像是依赖于运气,并不是可靠成熟的做法,所以意义不大。毕竟身份就是很容易伪造的,即便是看起来很靠谱的硬件信息。

总结,其实当选择一些方案的时候,还是更应当选择社区成熟的方案。jwt的优势还是在于简单,服务器无需管理用户状态,但劣势也是无法管理用户状态,无法实现特定状态管理功能。配合https和只读cookie其实token被盗用的概率很小,除非你的设备丢失了。

update ======== jwt和token的不同:

后端获得jwt不需要再去数据库校验,直接可以当成合法的身份标识。而普通的token交给后端,后端还需要查数据库校验是否合法,因此后端一旦做分布式,这个token就会是一件麻烦事