Redis是blacklist的一个不错的选择,它可以快速访问内存中的列表。然后,在运行在每个授权请求上的某种中间件中,您应该检查所提供的令牌是否在Blacklist中。如果是,则应该抛出未授权错误。如果不是,则让它离开,JWT验证将处理它并确定它是否过期或仍然有效。 有关更多信息,请参阅How to log out when using JWT。Arpy Vanyan(credit and reference)
var redis = require('redis');
var JWTR = require('jwt-redis').default;
var redisClient = redis.createClient();
var jwtr = new JWTR(redisClient);
jwtr.sign(payload, secret)
.then((token)=>{
// your code
})
.catch((error)=>{
// error handling
});
router.post('/logout', auth, async(req, res) => {
try{
let randomNumberToAppend = toString(Math.floor((Math.random() * 1000) + 1));
let randomIndex = Math.floor((Math.random() * 10) + 1);
let hashedRandomNumberToAppend = await bcrypt.hash(randomNumberToAppend, 10);
// now just concat the hashed random number to the end of the token
req.token = req.token + hashedRandomNumberToAppend;
return res.status(200).json('logout');
}catch(err){
return res.status(500).json(err.message);
}
});
8条答案
按热度按时间b09cbbtk1#
JWT存储在浏览器上,因此删除客户端的cookie
如果您还需要在令牌到期之前从服务器端使其失效,例如帐户被删除/阻止/暂停,密码更改,权限更改,用户被管理员注销,请查看Invalidating JSON Web Tokens了解一些常见技术,如创建黑名单或轮换令牌。
bzzcjhmw2#
在创建令牌后,您无法手动使其过期。因此,您无法在服务器端使用JWT注销,就像使用会话一样。
JWT是无状态的,这意味着你应该把你需要的所有东西都存储在payload中,而不需要对每个请求执行DB查询。但是如果你计划有一个严格的注销功能,即使你已经从客户端清理了令牌,也不能等待令牌自动过期,那么你可能需要忽略无状态逻辑并执行一些查询。那么有什么解决方案呢?
黑名单
所有不再有效且尚未过期的令牌的“黑名单”。您可以使用具有TTL选项的DB,该选项将被设置为令牌过期前的剩余时间。
Redis
Redis是blacklist的一个不错的选择,它可以快速访问内存中的列表。然后,在运行在每个授权请求上的某种中间件中,您应该检查所提供的令牌是否在Blacklist中。如果是,则应该抛出未授权错误。如果不是,则让它离开,JWT验证将处理它并确定它是否过期或仍然有效。
有关更多信息,请参阅How to log out when using JWT。Arpy Vanyan(credit and reference)
aij0ehis3#
从客户端注销时,最简单的方法是从浏览器的存储中删除令牌。
但是,如果你想销毁Node服务器上的token怎么办-
JWT包的问题是它没有提供任何方法或途径来销毁令牌。
因此,为了在服务器端销毁令牌,您可以使用jwt-redis包而不是JWT
本库(jwt-redis)完全重复了jsonwebtoken库的全部功能,但有一个重要的补充。Jwt-redis允许您将token标签存储在redis中以验证有效性。redis中没有token标签会导致token无效。要销毁jwt-redis中的token,有一个destroy方法
它是这样工作的:
1)从npm安装jwt-redis
2)创建-
3)验证-
4)毁灭-
注意:您可以在登录token时提供expiresIn,与JWT提供的一样。
n6lpvg4x4#
如果您只想删除令牌,则只需将其从前端应用程序中删除即可。在这种情况下,请清除存储令牌的cookie
另一方面,如果你想使令牌无效,有几种方法可以做到这一点,下面是一些方法
(1)如果所有生成的token都存储在后端,那么就像清除存储一样简单,如果token已经Map到用户,那么您可以只清除特定用户的token。
(2)您可以在user中添加类似invalidate_before这样的日期字段,在更改密码、从所有设备注销等情况下更新该日期字段。只需将invalidate_before更新为currentTime即可()。每次创建新令牌时,将创建时间添加到令牌有效负载中,要验证传入请求上的令牌,只需检查有效负载中的创建时间是否大于数据库中该用户的invalidate_before时间
**(3)当您创建一个新用户时,只为该用户创建一个密钥,然后您可以使用该特定密钥对每个用户令牌进行签名,就像在(2)**事件中一样,如更改密码,从所有设备注销等,应该创建一个新的密钥。这样您也可以通过检查令牌签名来使其无效。
**(2)和(3)**的开销是,验证将是一个两步过程,并且它涉及数据库阅读
编辑:对于**(3),您可以使用盐来代替(最终的秘密将是公共秘密+特定用户的盐**),因此您可以通过更改盐来使单个用户的令牌无效,或者通过更改公共秘密来使所有用户的令牌无效
rxztt3cl5#
您可以为令牌添加“发行时间”,并为服务器上的每个用户维护“最后注销时间”。当您检查令牌有效性时,还可以检查“发行时间”是否在“最后注销时间”之后。
krugob8w6#
虽然其他答案为各种设置提供了详细的解决方案,但这可能会帮助那些只在寻找一般答案的人。
有三个常规选项,选择一个或多个:
1.在客户端,使用javascript从浏览器中删除cookie。
1.在服务器端,将cookie值设置为空字符串或一些无用的值(例如
"deleted"
),并将cookie过期时间设置为过去的时间。1.在服务器端,更新存储在数据库中的refreshtoken。使用此选项可以从用户登录的所有设备注销用户(他们的refreshtoken将变为无效,他们必须重新登录)。
hsvhsicv7#
如果你使用的是passportJs的jwt策略,你可以通过改变
secretOrKey
来使tokes失效。它会使所有用户的tokes失效。我很确定你正在使用的auth库有一些类似的属性。
xyhw6mcr8#
好了,我尝试了一些我想分享的东西,我认为这是一个非常简单和有效的方法,所以基本上不是破坏你的令牌或黑名单,我们可以简单地在中间添加一个随机值,在一个随机索引中,甚至在它的末尾,就像一个随机数(或随机散列数)以使任何人更难反转它并获得先前有效的令牌,这样做会使此令牌无效,因此用户将无法访问任何地方,并且您可以从前端重定向用户以再次登录(或者甚至从后端,但我更喜欢如果前端这样做),所以用户注销,他们被重定向到登录页面,这一切都很好,这是我的代码。首先,我有一个认证中间件,如果令牌(密码和用户名)是好的,它附加令牌到req.token,所以每当我调用这个中间件,用户的令牌将被保存到req.token
现在它将concat散列随机数到令牌的末尾,这意味着它不再有效,因此用户将不得不再次登录,因为他们将被重定向到登录页面