销毁JSON Web令牌

时间:2017-04-24 14:49:12

标签: javascript json node.js token

这是真的让人困惑的事情。我。让我们假设您有一个REST API,您希望用户注销。登出后,应销毁jwt(json网络令牌),因此用户无法访问服务器的资源(即菜单,菜肴等)。

在我的情况下,用户可以注销,但他/她仍然可以执行所有请求(获取菜肴,发布和删除),直到令牌有效。这是我的代码。

verify.js

var User = require('../models/user');
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var config = require('../config.js');

exports.getToken = function (user) {
      return jwt.sign(user, config.secretKey, {
          expiresIn: 3600
      });
};

exports.verifyOrdinaryUser = function (req, res, next) {
    // check header or url parameters or post parameters for token
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    // decode token
    if (token) {
        // verifies secret and checks exp
        jwt.verify(token, config.secretKey, function (err, decoded) {
           if (err) {
               var err = new Error('You are not authenticated!');
               err.status = 401;
               return next(err);
           } else {
               // if everything is good, save to request for use in other routes
               req.decoded = decoded;
               next();
           }
        });
     } else {
        // if there is no token
        // return an error
        var err = new Error('No token provided!');
        err.status = 403;
        return next(err);
     }
};

我在1小时后使令牌无效。

users.js 我在其中设置了所有路线及其任务。即 localhost:3000 / users / login localhost:3000 / users / register localhost:3000 / users / logout 。如此。

var express = require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/user');
var Verify    = require('./verify');
/* GET users listing. */
router.get('/', function(req, res, next) {
   res.send('respond with a resource');
});

router.post('/register', function(req, res) {
    User.register(new User({ username : req.body.username }),
    req.body.password, function(err, user) {
        if (err) {
           return res.status(500).json({err: err});
        }
        passport.authenticate('local')(req, res, function () {
             return res.status(200).json({status: 'Registration Successful!'});
        });
    });
});

router.post('/login', function(req, res, next) {
    passport.authenticate('local', function(err, user, info) {
      if (err) {
        return next(err);
      }
      if (!user) {
        return res.status(401).json(
            err: info
          });
      }
      req.logIn(user, function(err) {
        if (err) {
          return res.status(500).json({
             err: 'Could not log in user'
          });
      }

      var token = Verify.getToken(user);
      res.status(200).json({
         status: 'Login successful!',
         success: true,
         token: token
      });
   });
 })(req,res,next);
});

router.get('/logout', function (req, res) {
    req.logout();
    res.status(200).json({
       status: 'Bye!'
    });
});

module.exports = router;

似乎退出方法 req.logout ,不起作用:(。有什么想法吗?

谢谢,

西奥。

2 个答案:

答案 0 :(得分:2)

如果所有数据都在客户端,则无法注销具有有效令牌的用户。您需要在服务器上存储一些状态,以区分您明确注销的用户和您没有注销的用户,并且每次都检查此状态。如果所有数据都完全在JWT令牌中,那么你就无法做任何让它无效的事情(除了改变你的所有令牌无效的秘密,而不仅仅是这个)。

您实际上发现了完全基于令牌本身中包含的数据使用身份验证的主要缺点。这些令牌不能无效。一旦他们出去,那么必须假设他们是活跃的。你只能要求客户忘记它,但不能信任客户端。

理论上你可能有一个像Redis这样的快速数据存储,你可以保存所有有效的令牌,并从那里删除令牌以强制注销,并在每次请求时检查这个存储,以了解谁仍然登录,谁不是,但如果你这样做,那么你可能会首先将会话数据存储在Redis中,并只向该客户端提供一些随机密钥到该数据存储。

答案 1 :(得分:2)

JWT旨在成为无国籍人士。这意味着所需的所有信息都包含在令牌本身中。

由于已经创建了令牌,因此注销将不会影响其有效性。

这使得您需要保留“无效”标记的列表,这意味着您再次引入了状态。

如果您只关心同一台计算机上的后续用户,则可以在注销时删除令牌,从而保留无状态,但这不能防止已捕获令牌的情况。