比较密码 BcryptJS
Posted
技术标签:
【中文标题】比较密码 BcryptJS【英文标题】:Compare passwords BcryptJS 【发布时间】:2017-02-25 20:41:02 【问题描述】:所以我正在尝试构建一个非常基本的用户登录。我正在尝试创建一个用户,然后使用这些凭据登录并取回 JSON Web 令牌。我被困的地方是尝试比较密码然后发送响应。
步骤:
创建用户:
-
输入邮箱和密码
盐/哈希用户密码
将用户存入数据库
返回成功
登录
-
通过请求电子邮件值查找用户
如果找到比较密码
密码好发送 JSON Web Token
用户模型
email:
type: String,
required: true,
unique: true
,
password:
type: String,
required: true
用户路线
var express = require('express');
var router = express.Router();
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
// Create User
...
bcrypt.genSalt(10, function(err, salt)
bcrypt.hash("superSecret", salt, function(err, hash)
user.password = hash;
user.save();
res.json(success: true, message: 'Create user successful');
);
);
...
// Login
...
bcrypt.compare(req.body.password, 'superSecret', function(err, res)
if(req.body.password != user.password)
res.json(success: false, message: 'passwords do not match');
else
// Send JWT
);
所以这里的两个问题是,我无法发送响应,也无法比较密码。完全坚持这一点,任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:如doc 中所述,您应该像这样使用bcrypt.compare
:
bcrypt.compare(req.body.password, user.password, function(err, res)
if (err)
// handle error
if (res)
// Send JWT
else
// response is OutgoingMessage object that server response http request
return response.json(success: false, message: 'passwords do not match');
);
这是一篇关于Password Authentication with Mongoose (Part 1): bcrypt的好帖子
【讨论】:
那是我之前参考过的一篇文章,一开始没有注册,不过再看看吧。另一个问题是在 compare 方法中运行res.[send][json]
将导致 unresolved method or function error
。所以解决这个问题的唯一方法似乎是设置某种类型的回调View Gist
变量名冲突的问题,res.json
应该是response.json
,其中response
指的是OutgoingMessage。我已经更新了答案,请检查一下。【参考方案2】:
如果我们在浏览器(HTML)中使用 bcryptjs,那么您可以添加 bcryptjs CDN 来执行此操作。
CDN - https://cdn.jsdelivr.net/npm/bcryptjs@2.4.3/dist/bcrypt.js
示例-
HTML-(在标签中添加上面的CDN)
JS-
var bcrypt = dcodeIO.bcrypt;
/** One way, can't decrypt but can compare */
var salt = bcrypt.genSaltSync(10);
/** Encrypt password */
bcrypt.hash('anypassword', salt, (err, res) =>
console.log('hash', res)
hash = res
compare(hash)
);
/** Compare stored password with new encrypted password */
function compare(encrypted)
bcrypt.compare('aboveusedpassword', encrypted, (err, res) =>
// res == true or res == false
console.log('Compared result', res, hash)
)
如果你想在 Nodejs 中做同样的事情
/** 像下面这样导入 lib 并使用与上面写的相同的功能 */
var bcrypt = require('bcryptjs')
【讨论】:
鲍勃是你的叔叔。 2021年有效【参考方案3】://required files
const express = require('express')
const router = express.Router();
//bcryptjs
const bcrypt = require('bcryptjs')
//User modal of mongoDB
const User = require('../../models/User')
//Post request for login
router.post('/', (req, res) =>
//email and password
const email = req.body.email
const password = req.body.password
//find user exist or not
User.findOne( email )
.then(user =>
//if user not exist than return status 400
if (!user) return res.status(400).json( msg: "User not exist" )
//if user exist than compare password
//password comes from the user
//user.password comes from the database
bcrypt.compare(password, user.password, (err, data) =>
//if error than throw error
if (err) throw err
//if both match than you can do anything
if (data)
return res.status(200).json( msg: "Login success" )
else
return res.status(401).json( msg: "Invalid credencial" )
)
)
)
module.exports = router
【讨论】:
【参考方案4】:据我所知,您的逻辑是正确的。
如果您使用的是猫鼬,我建议您使用 pre 'save' 钩子。
用户架构
userSchema.pre('save', function(next)
// only hash the password if it has been modified (or is new)
if (!this.isModified('password'))
return next();
// generate a salt
return bcrypt.genSalt(10, function(error, salt)
if (error)
return next(error);
// hash the password using the new salt
return bcrypt.hash(this.password, salt, function(error, hash)
if (error)
return next(error);
// override the cleartext password with the hashed one
this.password = hash;
return next();
);
);
);
userSchema.methods.comparePassword = function(passw, cb)
bcrypt.compare(passw, this.password, function(err, isMatch)
if (err)
return cb(err, false);
return cb(null, isMatch);
);
;
在你的路线中:
登录
...
return user.comparePassword(password, function(error, isMatch)
var payload =
iat: Math.round(Date.now() / 1000),
exp: Math.round((Date.now() / 1000) + 30 * 24 * 60),
iss: 'Whatever the issuer is example: localhost:3000',
email: user.email
;
var token = jwt.encode(payload, 'secret');
if (isMatch && !error)
// if user is found and password is right create a token
return res.json(
success: true,
token: `JWT $token`,
user: user,
msg: 'Authentication was succesful'
);
return next(code: 401, msg: 'Password is incorrect');
);
);
创建用户
// Pre hook will take care of password creation
return user.save()
.then(function(user)
var payload =
iat: Math.round(Date.now() / 1000),
exp: Math.round((Date.now() / 1000) + 30 * 24 * 60),
iss: 'Whatever the issuer is example: localhost:3000',
email: user.email
;
var token = jwt.encode(payload, 'secret');
return res.status(201).json(user, token: `JWT $token`, msg: 'User was succesfully created');
)
.catch((err) => next(err));
【讨论】:
所以我采纳了您的建议并逐个分解。但是,看起来user is undefined
在调用User.save()...
时正在发生,这与“预钩子”有关。我已经添加了这两个要点,因此维护路线和模型会更容易一些。再次感谢您的帮助user modeluser route
所以我更新了 2 Gist,用户对象现在正在传递到预保存钩子中,但是 this.password
是未定义的。我试过user.password
但也无济于事
看起来return bcrypt.genSalt(10, function(error, salt)
是无法调用this
的地方
所以密码现在正在被散列,但回调永远不会返回到路由。 return bcrypt.hash() ... newUser.password = hash; return next(); // everything stops here, callback never happens ...
【参考方案5】:
bcrypt.compare(req.body.password, user.password, function(err, results)
if(err)
throw new Error(err)
if (results)
return res.status(200).json( msg: "Login success" )
else
return res.status(401).json( msg: "Invalid credencial" )
)
【讨论】:
以上是关于比较密码 BcryptJS的主要内容,如果未能解决你的问题,请参考以下文章