传说中的jwt,我们来征服一下( 四 )


关于这个问题 , 小q也在上一篇文章中说明了 。 我们有两种配置方式可以完成swagger的权限令牌输入 。
下面这张图 , 就是配置的效果 。 你可以参阅《这篇文章》来完成配置 。
传说中的jwt,我们来征服一下文章插图
5. 它安全么?从我们刚开始的截图里面 , 就可以看出jwt的这一长串信息 , 是可以在客户端直接看到明文的 。 这就很容易让人产生怀疑 , 里面的内容是可以篡改的么?
我们随便复制了其中的一部分 , 然后使用base64解码 。 结果发现它果然是明文 。
传说中的jwt,我们来征服一下文章插图
其实 , 如果篡改了其中的明文信息 , 然后使用重新使用Base64编码塞进去 , 是不能通过验证的 。 这就是我们serect密钥的作用 。
在Java中 , 这个密钥 , 需要是Base64的 , 可以使用JDK的工具类生成 。
String key = new String(Base64.getEncoder().encode("lk234jlk80234lsd可连接克里斯朵夫isofios23u8432ndsdfsokjjjsklfjslk%^这个密钥可以是非常复杂的 , 除非它泄漏了 , 否则我们的jwt信息很难被篡改 。 所以 , 即使你看到的是明文 , 你也改不了 , 所以它是安全的 。
6. jwt事件中的问题从上面的描述中 , 我们可以看到 , 使用jwt来实现登录 , 是没有什么问题的 。 它的实现方式简单 , 易于扩展 , 可以替代cookie和session来完成登录、权限相关的功能 。 它的好处还有更多 。 首先 , 客户端可以用统一的方式进行处理 , 比如Android , IOS , Web端等 。 另外 , jwt支持跨域 。 这个是相对于Cookie来说的 , 因为jwt可以把信息放在header里 , 或者直接作为参数进行传递 。
问题也是有的 , 先说性能方面的:

  • 要占带宽 。因为你每次都需要把这个token进行传递 。 通常情况下 , 我们只在playload里存放用户id , 但如果你有更多的属性比如权限等 , 这个串将会变的非常大 。 如果请求量比较高 , 这个开销还是挺吓人的
  • 用户信息需要重复拉取 无状态意味着服务端不会保存登录信息 , 这就需要每次请求都拉取一下用户信息 。 一般来说这些信息从数据库中拉取是不合适的 , 你需要一个类似redis的缓存前置 。 但不论怎么做 , 都不如session来的快捷 。 这样你可能会考虑堆内缓存 , 来模拟session的那一套 。
其他使用问题 。
  • token注销 。如果是单纯的无状态 , 对jwt token的注销就会变的非常困难 。 如果token泄露 , 你甚至没有任何办法来防治这些不安全的请求 。 这是因为失效日期是写在token里的 , 你无法对其作出改动 。
  • token续租 。另外一个问题就是token的续租问题 。 比如你的token约定是在半个小时之后失效 , 那即使你在第29分钟进行了操作 , 这个token还是在约定的时间失效 。 这在使用人员眼里 , 看起来就会特别的怪异 。
为了这解决这些问题 , 我们需要把服务无状态这个属性收敛一下 。 token生成后 , 在服务端保存一份(redis , nosql之类) , 然后再对这些token进行刷新或者注销操作 。
但如果你不并不care这些问题 , 假定token非常安全 , 不会泄漏 , 那就可以签发一个超时时间很长的token , 每次登录都生成一个 , 废掉之前的token 。 这样 , 那些老的token虽然存在过 , 但是再也没有人知道它们了 。 这些token此时就变成了幽灵 。
总结本篇文章简单的介绍了jwt , 然后以springboot服务为例 , 看了一个集成案例 。 最后 , 讨论了jwt的优缺点 。 可以看到 , 对于一个普通的应用 , jwt可以做到真正的服务解藕 , 拿着token这个通行证 , 即可穿梭在不同的系统之间 。


推荐阅读