简体   繁体   English

用Bluebird宣传bcrypt-nodejs

[英]Promisifying bcrypt-nodejs with Bluebird

I'm using NodeJS, with bcrypt-nodejs ( https://github.com/shaneGirish/bcrypt-nodejs ) and Bluebird for promises. 我正在使用NodeJS,使用bcrypt-nodejs( https://github.com/shaneGirish/bcrypt-nodejs )和Bluebird进行承诺。 Came up with this code and been wondering if there is better way to do the same thing. 提出这个代码,并想知道是否有更好的方法来做同样的事情。 I have module with: 我有模块:

var Promise = require("bluebird"),
    bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'));

// ....[some othe code here]

    Users.prototype.setPassword = function(user) {

        return bcrypt.genSaltAsync(10).then(function(result) {
            return bcrypt.hashAsync(user.password, result);
        });

    };

then from another module I call users.setPassword as below: 然后从另一个模块我调用users.setPassword如下:

app.post('/api/v1/users/set-password', function(req, res, next) {
    users.setPassword(req.body).then(function(result) {

        // Store hash in your password DB.
        console.log(result[1]);

        res.json({
            success: true
        })
    })
        .catch(function(err) {
            console.log(err);
        });
});

It always ends up with "[Error: No callback function was given.]" message as bcrypt.hashAsync seems to require 4 parameters. 它始终以“[错误:没有给出回调函数。]”消息结束,因为bcrypt.hashAsync似乎需要4个参数。 Original, non-promisified hash method requires 3 only though. 原始的,非promisified hash方法只需要3。 When I add empty callback to hashAsync , it works fine: 当我向hashAsync添加空回调时,它工作正常:

Users.prototype.setPassword = function(user) {

    return bcrypt.genSaltAsync(10).then(function(result) {
        return bcrypt.hashAsync(user.password, result,function() {});
    });

};

Is there any better way to do this, without providing empty callback as above? 有没有更好的方法来做到这一点,而不提供如上所述的空回调?

EDIT: 编辑:

In response to Bergi's comment.. the function will set password eventually, I just didn't get that far when posted the question. 为了回应Bergi的评论..函数最终将设置密码,我刚刚发布问题时没那么做。 Now got this far, please let me know if something is not quite right though: 现在到目前为止,如果事情不太正确,请告诉我:

 Users.prototype.setPassword = function(user) {


        return bcrypt.genSaltAsync(10).then(function(result) {
            return bcrypt.hashAsync(user.password, result, null);
        })
        .then(function(result) {
                // store in database
                console.log("stored in database!");
                return result;
            });

    };

bcrypt.hashAsync seems to require 4 parameters. bcrypt.hashAsync似乎需要4个参数。 Original, non-promisified hash method requires 3 only though. 原始的,非promisified哈希方法只需要3。

It's the other way round rather. 反之亦然。 From the docs : 来自文档

hash(data, salt, progress, cb)

  • data - [REQUIRED] - the data to be encrypted. data - [REQUIRED] - 要加密的数据。
  • salt - [REQUIRED] - the salt to be used to hash the password. salt - [REQUIRED] - 用于散列密码的salt。
  • progress - a callback to be called during the hash calculation to signify progress progress - 在哈希计算期间调用以表示进度的回调
  • callback - [REQUIRED] - a callback to be fired once the data has been encrypted. callback - [REQUIRED] - 数据加密后要触发的回调。

The original method took 4 arguments, hashAsync will take 3 and return a promise. 原始方法有4个参数, hashAsync将取3并返回promise。

However, in your code you were only passing two. 但是,在您的代码中,您只传递了两个。 You don't need to pass an empty function though, that the parameter is not [REQUIRED] means you can pass null (or any other falsy value) for it. 您不需要传递一个空函数,该参数不是[REQUIRED]意味着您可以为它传递null (或任何其他虚假值)。 bcrypt will create such an empty function itself . bcrypt 会自己创建一个空函数 So use 所以使用

function (data) {
    return bcrypt.genSaltAsync(10).then(function(result) {
        return bcrypt.hashAsync(data.password, result, null);
    });
}

This is my promisified bcrypt from a project I did a while back. 这是我在一段时间内做过的项目中我的承诺的bcrypt。 Bluebird isn't really necessary for such a small, simple library. Bluebird对于这么小而简单的库来说并不是必需的。

module.exports = {
   makeUser: function(username, password){
    return new Promise(function(resolve, reject) {
      bcrypt.genSalt(10, function(err, salt){
        bcrypt.hash(password, salt, null, function(err, hash) {
          if (err) {
            console.log("hashing the password failed, see user.js " + err);
            reject(err);
          }
          else {
            console.log("hash was successful.");
            resolve(hash);
          }
        })
      })
    })
    .then(function(hash){
      return db.createUser(username, hash)
    })
  },

  login: function(username, password){
    return db.userFind(username)
    .then(function(userObj){
      if(!userObj){
        console.log("did not find " + username + " in database.");
        return new Promise(function(resolve, reject){ 
          resolve({login:false, message:"Your username and/or password are incorrect."})
        }
      }
      else {
        console.log("found user: " + userObj._id, userObj);
        return new Promise(function(resolve, reject){
          bcrypt.compare(password, userObj.hashword, function(err, bool) {
            resolve({bool:bool, 
              user:userObj._id,
              mindSeal: userObj
            })
          })
        })
      } 
    })
  }
}

Example Usage: 用法示例:

app.post('/signup', function(req, res) {
  var username = req.body.username;
  var password = req.body.password;
  var user = handler.userExists(username)
  .then(function(answer){
    if (answer !== null){
      console.log(req.body.username + " was taken")
      res.send({login: false, message: req.body.username + " is taken"});
      return null;
    } else if (answer === null) {
      console.log("username not taken")
      return handler.makeUser(username, password);
    }
  })
  .catch(function(err){
    console.log("error during user lookup:", err);
    res.status(404).send({message:"database error:", error:err});
  })

  if (user !== null){
    user
    .then(function(x){
      console.log("this is returned from handler.makeUser: ", x)
      console.log(x.ops[0]._id)
      req.session.user = x.ops[0]._id;
      var mindSeal = { 
        userSettings: {
          username: x.ops[0]._id,
          newCardLimit: null,
          tValDefault: 128000000, 
          lastEdit: req.body.time, 
          todayCounter: 0,
          allTimeCounter: 0,
          cScaleDefault: {0: 0.9, 1: 1.2, 2: 1.8, 3: 2.5},
          accountMade: req.body.time
        },
        decks: {}
      };
      handler.setMindSeal(req.session.user, mindSeal, req.body.time);
      res.send({
        login: true, 
        mindSeal: mindSeal
      });
    })
    .catch(function(error){
      console.log("make user error: " + error);
      res.status(401).send({message:"failed.",error:error,login:false});
    })
  }

});

app.post('/login', function(req, res) {
  var username = req.body.username;
  var password = req.body.password;
  handler.login(username, password)
  .then(function(obj){
    if (obj.bool){
      console.log("username and password are valid. login granted.");
      req.session.user = obj.user;
      console.log("obj is:", obj)
      var mindSeal = {decks:obj.mindSeal.decks, userSettings:obj.mindSeal.userSettings};
      console.log("mindSeal sending:", mindSeal);
      res.status(200).send({
        login: true, 
        message:"Login Successful", 
        mindSeal: obj.mindSeal
      });
    }
    else {
      console.log("password invalid")
      res.status(401).send({login: false, message:"Your username and/or password are incorrect."})
    }
  })
  .catch(function(error){
    console.log(error);
    res.status(404).send({message:"database error:", error:err});
  })
});

conceptual example only; 仅概念性示例; borrowed and slightly modified some old code of mine on the fly. 借用并略微修改了我的一些旧代码。 Working code (I see things I'd like to improve in it now, but it works) here: https://github.com/finetype/mindseal/blob/master/server.js 工作代码(我现在看到我想改进的东西,但它有效): https//github.com/finetype/mindseal/blob/master/server.js

Maybe you could use another bcrypt library , with a better API which removes the need for promises. 也许你可以使用另一个bcrypt库 ,使用更好的API来消除对promises的需求。

Users.prototype.setPassword = function(user) {
    return TwinBcrypt.hashSync(user.password, 10);
};

Or, with progress tracking : 或者,通过进度跟踪:

Users.prototype.setPassword = function(user) {

    function progress(p) {
        console.log( Math.floor(p*100) + '%' );
    }

    TwinBcrypt.hash(user.password, 10, progress, function(result) {
        // store in database
        console.log("stored in database!");
        return result;
    });

};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM