比如token在1点钟生成,有效期1小时。但是1点半的时候用户退出登陆了,怎么在这个退出登陆的操作中将token主动失效?
没有办法,JWT设计本身就是无状态的
可以在token里面加个随机码,把随机码放到数据库里面。登陆成功就在数据库记录一下随机码,退出登陆和过期就把这条记录删掉。如果随机码存在就能成功登陆否则就失败。如果用持久型的redis做储存还方便些。 注意看9楼,看回复时间。4,5,8楼的方式会更好些
@zy445566 正解。。
用户退出登录看起来是一个前端的动作,这个时候把前端持久化的token删掉就行了啊
jwt生成的token都是保存在前端的(cookie,缓存等),用户退出登录删除token,最简单
redis存一下token黑名单
说用reidis的,那还不如用传统的模拟session呢 不然不还是每一次请求都要去中心化的redis校验一遍?
JWT 本身是无状态的。
已经签发就有效,除非更换签发密钥。
只要是需要查询来校验 token 的 (查询 redis/SQL 等)就失去了 JWT 的意义,那为什么要 JWT 呢
@jiyarong @pretty-foam @axetroy 是的,有用户主动操作在,确实没必要服务端强判断,前端丢弃确实好一些
@zy445566 @axetroy @JsonSong89
https://github.com/auth0/express-jwt#revoked-tokens
express 的 jwt 实现是支持 黑名单的,可以参考这个~
@zuohuadong 你给的这个不是黑名单吧,只不过是一个错误处理回调而已.
这里根本不需要考虑什么具体实现. 只说一个本质问题,没有持久化的db(redis,数据库),你如何判断一个与token无关的外部状态?
@JsonSong89 跟我读:Revoked tokens 稍微往上一点就能看到了。 对于无状态服务来说,确实存在 redis 或者 数据库里是合适一些,这些是具体的实现了。
function checkRevoked(decoded, callback) {
isRevokedCallback(req, dtoken.payload, function (err, revoked) {
if (err) {
callback(err);
}
else if (revoked) {
callback(new UnauthorizedError('revoked_token', {message: 'The token has been revoked.'}));
} else {
callback(null, decoded);
}
});
}
revoked的赋值过程和这个库没关系.
都不知道你发这个库什么意思,和这个帖子的主题有什么关系吗?
@JsonSong89 吊销token 不返回错误返回什么? 这个库是所有node.js 的 jwt库 里,唯一一个支持 黑名单的库,我发这个不合适?
原理上讲 就是 、
- 专门维护一套黑名单, 单实例放内存也好,多实例放 redis, 甚至数据库 哪怕 sqlite 也好 。
- 验证token 前,先看是不是黑名单里面的,是的话直接返回错误。
- 如果不是黑名单里的再走正常的 jwt 验证流程。
讨论问题为什么非要杠?
@zuohuadong 这也叫杠?现在是不是只要说的不和人心意就是杠啊?
题目问的是让token失效,这从原理上来讲就不可能.
前面也有人说的很清楚了,必须借助外部db来持久化状态 然后你at几个人,扔个链接过来,也不说清楚,说是jwt支持黑名单 搞半天还是借助db来实现的. 所以你把别人已经明确的东西再给人说一遍,还不说清楚,语气还特别嘚瑟… 到底是谁不好好讨论问题?
@zuohuadong 你这个库只涉及黑名单拒绝后的后续处理,然而这个帖子的关键点是黑名单的实现,你提到的最关键的1,和这个库无关吧. 所以我说你发错东西了.
@JsonSong89 楼上也说了,这样违反 jwt 的本质了。 唯一好结合的就是我提到的那个库。 而且目前除了我提到的库之外,node.js 其他 jwt 相关的库都没提黑名单的事情。 所以我贴的不合理?
@zuohuadong 为什么没什么人做这种库,就应为完全没必要. 而且两句代码就能搞定的事情,有什么好不好结合的 const blackTokenList = await getBlackTokenListFromRedis() const denyFlag = blackTokenList.includes(token) //然后你该干嘛干嘛 你就算要参与讨论,直接说这个重点不更有效率?
@JsonSong89 你这两句话有性能问题吧,我只需要判断token是否在redis黑名单里,没必要获取整个列表吧 应该const isRevoked =await redis.exists(‘revoked-’+tokenKey)
每个用户都有自己的秘钥,注销之后就把秘钥修改一次
@zy445566 如果保存随机码,那为何不直接保存token本身呢。
@waitingsong 你看9楼,再看回复时间
无状态的认证结合有状态的认证,在jwt后再加一层后端可以统一控制的存储,不管是redis还是其他数据库,然后就可以通过控制这个存储的状态来控制认证的状态,但事实上这样就失去了jwt的意义
@zy445566 嗯,明白是很老的帖子。 我的意思是保存一个和token一一对应的随机数,与保存这个token本身应该是没区别的吧(暂时不考虑token字符串长度关联的性能问题) 。
@waitingsong 是的,当时没考虑清楚。就直接服务端思维套上了