卧槽, jwt 这种认证方式竟然不需要在服务器本地存信息?

2019-07-06 03:43:58 +08:00
 51300520

以往我登录验证一直是生成 token,发给客户端,自己存数据库,下次客户端发来我从数据库里面取出对比。

刚调试一个 golang 的登录程序,我就纳闷,他生成一个 token 返回给客户端,我重启服务程序后该 token 竟然还能准确认证。该 token 我并没有在服务器上落地,重启后它是怎么还能继续验证的? 我以为是不是 jwt 包在哪里偷偷落地了,于是单步仔细检查了一番,发现没有。 于是 google,竟然发现这玩意不需要落地就就能一直验证。 太TM神奇了。。。。

顺便问句,这玩意可靠吗?容易被破解不?如果可靠,那以后登录验证就用它了

9003 次点击
所在节点    信息安全
31 条回复
geelaw
2019-07-06 04:05:10 +08:00
JWT 是数字签名,所以只需要 public key 和受信任的时间即可验证有效性
yamedie
2019-07-06 06:16:58 +08:00
服务端不存库的话,无法解决单设备单点登录,另外还有 token 被盗用的问题。楼下讲讲如何魔改解决这俩问题?
yamedie
2019-07-06 06:21:12 +08:00
关于 token 被盗用,忽然想到也许可以把设备的一部分特征放进 payload 里,比如 ua ?但那样会导致 token 变得巨长。。。
yamedie
2019-07-06 06:25:17 +08:00
@yamedie 自问自答:也许可以把 ua 散列成摘要后,取几位,作为一个更短的设备特征摘要,放进 payload。缺点是加重服务端验证时的 cpu 负载
iBenlim
2019-07-06 06:43:54 +08:00
而且居然还可以在 Token 中存 UserId …
mcfog
2019-07-06 06:44:45 +08:00
不建议 jwt 做一般业务的会话认证

详情 http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
virusdefender
2019-07-06 07:29:20 +08:00
你会发现很多 jwt 的实现都没有改密码之后失效老 token 的功能,只能自己再包装下
lhx2008
2019-07-06 07:45:06 +08:00
简单业务,对安全没有要求可用。
缺点不少,一个是加解密费时间,一个是 jwt 格式改了之后,后端适配很烦,一个是服务器不好做黑名单,改密码之后,jwt 仍然是有效的,必须建立一个 k-v 的黑名单,那么问题来了,已经建了这个名单,和直接存个用户 Object 有啥区别
keepeye
2019-07-06 09:22:50 +08:00
我们正考虑不再使用 jwt,最大的原因是没法清除单个会话
dodo2012
2019-07-06 09:24:08 +08:00
不使用 jwt 的话,现在有啥更合适的
hst001
2019-07-06 09:29:33 +08:00
jwt 有 jwt 的问题,当时考察了一番,决定不使用,纯添麻烦。
sparrww
2019-07-06 09:42:41 +08:00
@lhx2008 改密码的问题,生成 token 的时候把密码作为加密的一部分是可以解决的
geelaw
2019-07-06 10:02:01 +08:00
@lhx2008 #8 可以给用户存一个 version number,在用户变更安全信息或者撤销所有会话的时候增加之,只有 version number 足够高的签名才有效就行了。

@keepeye #9 赞同。

(如果引入 state 的话 JWT 就属于传统 session 的特例了)
laoyur
2019-07-06 10:49:53 +08:00
所以楼主的心情是:
我擦,发现新大陆,这么好用的东东,赶紧去 v2 找认同 --> 一堆人劝退 --> 我勒个去,白高兴一场
honeycomb
2019-07-06 10:59:55 +08:00
@lhx2008 可以用 bloom filter 作黑名单,空间要求比 k-v 小
MonoLogueChi
2019-07-06 11:05:55 +08:00
jwt 好像是根据密钥和时间戳验证的,只要有密钥能用,每到过期时间,就一直可以用
loading
2019-07-06 12:36:08 +08:00
jwt 那串东西分三部分,前两部分都是可公开的东西,里面有 uid 什么的,最重要是有这个 token 的过期时间(这是实际时间,验证的时候是你服务器的时间,所以没有时空问题),然后这些信息 base64 了一下。

那么如何防止别人伪造呢?

第三段就是保证。服务器收到前两段,然后加入一个自定义的固定字符串(slat),然后用私钥加密,得到第三段。

只要拿到这一段字符,基本就可以为所欲为,只要没超期。

为了拦截一个已知已经被泄露的 token,jwt 里面很多时候就又会加上一个对应的 keyid,而这个 keyid 又需要在服务器进行保持,走回了老路。

jwt 是一种轻量的登录方式,因为没魔改的话不需要跑数据,只需要加解密计算,这就不会遇到数据库瓶颈了,对不是苛刻安全要求高并发非常合适。

没有银弹,看场合。
jedrek
2019-07-06 12:39:00 +08:00
51300520
2019-07-06 13:20:47 +08:00
这个东西好像很适合网站啊,网站一般允许多点登录
51300520
2019-07-06 13:21:03 +08:00
@laoyur
哈哈哈哈哈哈

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/580498

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX