问题
So I'm trying to build a very basic user login. I'm trying to create a user, then login with those credentials and get back a JSON Web Token. Where I'm stuck is trying to compare the passwords then send a response.
Steps:
Create User:
- enter email and password
- salt/hash user password
- store user into database
- return success
Login
- find user by request email value
- if found compare passwords
- passwords good send JSON Web Token
User Model
email:{
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
User Routes
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
}
});
So the two problems here is that, I can't send a response nor can I compare the password. Just completely stuck on this, any help would be greatly appreciated.
回答1:
As described in the doc, you should use bcrypt.compare
like that:
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'});
}
});
And here is a nice post about Password Authentication with Mongoose (Part 1): bcrypt
回答2:
If we you to use bcryptjs in browser(HTML) then you can add bcryptjs CDN to do this.
CDN - https://cdn.jsdelivr.net/npm/bcryptjs@2.4.3/dist/bcrypt.js
Example-
HTML- (Add above CDN in tag)
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)
})
}
If you want to do same in Nodejs
/** Import lib like below and use same functions as written above */
var bcrypt = require('bcryptjs')
回答3:
From what I can see your logic is correct.
If you are using mongoose I suggest you to use the pre 'save' hook.
User Schema
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);
});
};
And in your routes:
Login
...
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'});
});
});
Create user
// 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));
回答4:
//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
回答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" })
}
})
来源:https://stackoverflow.com/questions/40076638/compare-passwords-bcryptjs