Rest API - 在JSON响应中获取密码是否安全

时间:2015-12-08 22:40:31

标签: json node.js rest

我正在使用Node.js编写Rest API并使用JWT。

我有以下路线来验证用户身份。

我想问一下,从方法user返回的User.findOne会返回正确的密码,因此我可以检查它是否正确。 但这样做安全吗?我做了一个console.log,它显示了密码(虽然是加密的),但仍然感觉不安全,因为有人肯定可以查看?

router.post('/authenticate', function(req, res) {

  // find the user
  User.findOne({
    name: req.body.name
  }, function(err, user) {

    if (err) throw err;

    if (!user) {
      res.json({ success: false, message: 'Authentication failed. User not found.' });
    } else if (user) {

      // check if password matches
      if (user.password != req.body.password) {
        res.json({ success: false, message: 'Authentication failed. Wrong password.' });
      } else {

        // if user is found and password is right
        // create a token
        var token = jwt.sign(user, app.get('superSecret'), {
          expiresInMinutes: 1440 // expires in 24 hours
        });

        // return the information including token as JSON
        res.json({
          success: true,
          message: 'Enjoy your token!',
          token: token
        });
      }

    }

  });
});

1 个答案:

答案 0 :(得分:2)

没有

此外,密码不应保存在数据库中加密,而是哈希。经典环境保存密码,例如md5(更常见)或bcrypt(更安全)散列。

这确保即使您的数据库被盗,也没有人会拥有您的用户的密码;没有办法“解密”哈希(不是一亿年)。

当用户登录时,您将输入的密码的哈希值与分配给用户的哈希值进行比较。您可以使用像bcrypt-nodejs

这样的优秀模块

修改

从技术方面来说,它并不危险。当您启动服务器时,JavaScript会编译您的代码并在V8引擎中执行结果。只要保存节点和MySQL之间的连接,就无法访​​问数据库返回的内容。 有人可能会转储服务器内存并希望找到合适的位。但如果有人获得了必要的许可,你就会注定失败。

我为你实现了一个例子,它没有经过测试,但应该告诉你它是什么意思。

router.post('/register', function(req, res) {
    bcrypt.hash(req.body.password, null, null, function(err, hash) {
        if (!err) {
            var newUser = new User({
                name: req.body.name,
                password: hash
            });

            newUser.save(); // ????
        }
    });
});
router.post('/authenticate', function(req, res) {
    User.findOne({
        name: req.body.name
    }, function(err, user) {
        var password = 'GP%Z!zvbk/9>Ss-R';
        var passwordHash = '$2a$10$W.zZPCaNOuR152I4qENKH.8h7I6BPcfCYBJqHPNXbVaBz0XWVxnBm'; // bcrypt of string ')RZK&M(QX"k188cw'

        if (user) {
            password = req.body.password;
            passwordHash = user.password;
        }

        bcrypt.compare(password, passwordHash, function(err, success) {
            if (success) {
                var token = jwt.sign(user, app.get('superSecret'), {
                    expiresInMinutes: 1440
                });

                res.json({
                    success: true,
                    message: 'Enjoy your token!',
                    token: token
                });
            }
            else {
                res.status(401).json({
                    success: false,
                    message: 'Authentication failed.'
                });
            }
        });
    });
});

注意:对于每个哈希操作,bcrypt默认使用随机盐。这意味着,无论何时散列给定输入,它每次都会产生不同的散列。然后将盐存储为哈希的一部分,然后可以对其进行验证。请查看Wikipedia以获取更多信息。