Node.js 如何在注销时销毁JWT令牌?

Node.js 如何在注销时销毁JWT令牌?,node.js,jwt,hapijs,Node.js,Jwt,Hapijs,我在hapijs中使用jwt插件和策略 我能够在登录用户时创建jwt令牌,并通过“jwt”策略使用相同的令牌对其他API进行身份验证 我正在将request.state.USER\u SESSION中的令牌设置为cookie,其中USER\u SESSION是令牌名称。此外,我没有将这些令牌保存在数据库中 但我如何在注销时销毁jwt令牌 请建议一种方法。JWT存储在浏览器上,因此删除客户端cookie的令牌 如果您还需要在到期之前使服务器端的令牌失效,例如帐户已删除/阻止/挂起、密码已更改、权限

我在hapijs中使用jwt插件和策略

我能够在登录用户时创建jwt令牌,并通过“jwt”策略使用相同的令牌对其他API进行身份验证

我正在将
request.state.USER\u SESSION
中的令牌设置为cookie,其中
USER\u SESSION
是令牌名称。此外,我没有将这些令牌保存在数据库中

但我如何在注销时销毁jwt令牌


请建议一种方法。

JWT存储在浏览器上,因此删除客户端cookie的令牌


如果您还需要在到期之前使服务器端的令牌失效,例如帐户已删除/阻止/挂起、密码已更改、权限已更改、用户已由管理员注销,查看一些常用技术,如创建黑名单或循环令牌

您不能在令牌创建后手动使其过期。因此,您不能像使用会话那样在服务器端使用JWT注销

JWT是无状态的,这意味着您应该将所需的一切存储在有效负载中,并跳过对每个请求执行DB查询。但是,如果您计划使用严格的注销功能,即不能等待令牌自动过期,即使您已经从客户端清除了令牌,那么您可能需要忽略无状态逻辑并执行一些查询。那么什么是解决方案

  • 设置令牌的合理过期时间

  • 注销时从客户端删除存储的令牌

  • 在每个授权请求中根据黑名单查询提供的令牌

黑名单 所有不再有效且尚未过期的代币的“黑名单”。您可以在文档上使用具有TTL选项的DB,该选项将设置为令牌过期之前的剩余时间量

雷迪斯 Redis是黑名单的一个很好的选择,它允许对黑名单进行快速内存访问。然后,在对每个授权请求运行的某种中间件中,您应该检查所提供的令牌是否在黑名单中。如果是,您应该抛出未经授权的错误。如果不是,让它去,JWT验证将处理它,并确定它是否过期或仍然有效


有关详细信息,请参阅。Arpy Vanyan(信用和参考)

在从客户端注销时,最简单的方法是从浏览器的存储中删除令牌

但是,如果要销毁节点服务器上的令牌,该怎么办?

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
    });
JWT包的问题在于它没有提供任何方法或方法来销毁令牌

因此,为了销毁服务器端的令牌,您可以使用jwt redis包而不是jwt

此库(jwt redis)完全重复了库jsonwebtoken的全部功能,只添加了一项重要内容。Jwt redis允许您在redis中存储令牌标签以验证有效性。redis中缺少令牌标签使得令牌无效。要销毁jwt redis中的令牌,有一种销毁方法

它是这样工作的:

1) 从npm安装jwt redis

2) 创建-

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
    });
3) 验证-

jwtr.verify(token, secret);
jwtr.destroy(token)
4) 销毁-

jwtr.verify(token, secret);
jwtr.destroy(token)

注意:您可以在令牌登录期间提供expiresIn,与JWT中提供的相同。

虽然其他答案提供了各种设置的详细解决方案,但这可能会帮助正在寻找一般答案的人

有三个常规选项,请选择一个或多个:

  • 在客户端,使用javascript从浏览器中删除cookie

  • 在服务器端,将cookie值设置为空字符串或无用的内容(例如
    “deleted”
    ),并将cookie过期时间设置为过去的时间

  • 在服务器端,更新存储在数据库中的refreshtoken。使用此选项可从用户登录的所有设备注销用户(其刷新令牌将变为无效,必须重新登录)


  • 您可以将“发布时间”添加到令牌中,并为服务器上的每个用户维护“上次注销时间”。当您检查令牌有效性时,还要检查“发出时间”是否在“上次注销时间”之后所以,我尝试了一些我想分享的东西,我认为这是一个非常简单和有效的方法,所以基本上不破坏你的令牌或黑名单,我们可以简单地在随机索引的中间附加一个随机值,甚至在它的末尾附加随机数(或者随机散列数)。为了让任何人都更难撤销它并获得以前有效的令牌,这样做会使该令牌无效,因此用户不会去任何地方,并且从前端您可以重定向用户以再次登录(或者甚至从后端重新登录,但如果前端这样做了,我更愿意这样做)用户注销后,他们会被重定向到登录页面,这一切都很好,这是我的代码。首先,我有一个身份验证中间件,如果令牌(密码和用户名)正常,它会将令牌附加到req.token,因此每当我调用此中间件时,用户的令牌将保存到req.token

    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);
        }
    });
    

    现在,它将把散列的随机数连接到令牌的末尾,这意味着它不再有效,因此用户将不得不再次登录,因为他们将被重定向到登录页面

    我同意您的回答。我正在通过'reply.state('USER_SESSION',{jwtToken});'其中USER_SESSION是cookie名称。所以,你能建议我应该运行什么命令来清除hapijs中的cookie状态吗?你在服务器端,不能强制浏览器删除cookie。但是,您可以将该值设置为空,并包含
    expires
    字段以使cookie值无效。看见您还可以使用javascript
    var delete\u cookie在客户端使cookie无效=