已解决:在节点js中解密电子邮件激活令牌后,我的代码无法加密保存在mongoDB中的密码,我该如何解决?
Solved: my code is unable to encrypt the password to save in mongoDB after email activation token is decrypted in node js, how can i solve it?
我正在尝试通过 MERN 实施 jwt 身份验证,在 nodejs 中,我使用电子邮件激活 link 将用户电子邮件和密码保存在 mongodb 中。这是我注册用户和激活用户的工作示例。我正在使用 sendgrid 发送电子邮件。
//for email verification test
signup = async (req, res) => {
const { username, email, password, passwordCheck, displayName } = req.body;
//validate
if (!username || !email || !password || !passwordCheck)
return res.status(400).json({
msg: "not all fields have been entered.",
});
if (password.length < 8)
return res.status(400).json({
msg: "The password needs to be at least 8 characters long.",
});
if (password !== passwordCheck)
return res
.status(400)
.json({ msg: "Enter the same password twice for verification." });
const existingUser = await User.findOne({ email: email });
if (existingUser)
return res
.status(400)
.json({ msg: "An account with this email already exists." });
const existingUserName = await User.findOne({ username: username });
if (existingUserName)
return res
.status(400)
.json({ msg: "An account with this username already exists." });
if (!displayName) displayName = email;
const token = jwt.sign(
{ username, email, password, passwordCheck, displayName },
process.env.JWT_SECRET,{expiresIn:'1000m'}
);
const msg = {
to: email, //receiver's email
from: "no-reply@test.com", // Change to your verified sender
subject: `Email verification link ${displayName}`,
text: "testing from local",
html: `<h2>Hi ${displayName}</h2> <br/>sends a message for verification test: http://localhost:3000/authentication/activate/${token}</p> <br/><p>Have a nice day</p>`,
};
sgMail.setApiKey(process.env.SENDGRID_SECRET_API);
sgMail
.send(msg)
.then((result) => {
res.json({ message: "Email activation link has been sent" });
})
.catch((error) => {
console.error(error);
res.status(500).json("Error");
});
}
router.post("/register", signup);
userActivation = (req, res)=>{
const { token } = req.body;
if(token){
jwt.verify(token, process.env.JWT_SECRET,function(err,decodeToken){
if(err){
return res.status(400).json({error:'Incorrect or expired link.'})
}
const { username, email, password, passwordCheck, displayName }=decodeToken;
const newUser = new User({
username,
email,
password,
displayName,
});
newUser.save((err,success)=>{
if(err){
console.log("Error in signup with account activation",err)
return res.status(400).json({error:"Error activating account"})
}
res.json({
message:"signup Success!!"
})
});
} );
} else{
return res.json({error:"Something went wrong"})
}
}
router.post("/email-activate",userActivation)
在使用 postman 保存用户和激活密钥时,在 mongodb 中密码以纯文本形式保存。由于安全问题,我不希望它以纯文本形式保存。我希望它以加密方式保存并尝试使用以下代码:
userActivation = async (req, res) => {
const { token } = req.body;
if (token) {
jwt.verify(token, process.env.JWT_SECRET, function (err, decodeToken) {
if (err) {
return res.status(400).json({ error: "Incorrect or expired link." });
}
const { username, email, password, displayName } = decodeToken;
console.log(password)
User.findOne({ email }).exec((err, user) => {
if (user) {
return res.status(400).json({ error: "Username with this email exists." })
}
const salt = bcrypt.genSalt();
bcrypt.hash(password, salt, (err, passwordHash)=>{
const newUser = new User({
username,
email,
password: passwordHash,
displayName,
});
console.log(password)
console.log(passwordHash)
newUser.save((err, success) => {
if (err) {
console.log("Error in signup with account activation", err);
return res.status(400).json({ error: "Error activating account" });
}
res.json({
message: "signup Success!!",
});
})
})
})
})
}
}
当我启动我的服务器并尝试通过 postman 使用激活密钥登录时,它向我发送了一个激活 link。当我尝试通过激活中的 postman 发送 post 请求时 link,postman 显示 404 状态“错误激活帐户”并且节点索引显示以下错误:
The server has started on port: 5000
MongoDB connected
**the real password is showing undecoded**
**the real password is showing undecoded**
undefined
Error in signup with account activation Error: user validation failed: password: Path `password` is required.
at ValidationError.inspect (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\error\validation.js:47:26)
at formatValue (internal/util/inspect.js:731:31)
at inspect (internal/util/inspect.js:295:10)
at formatWithOptionsInternal (internal/util/inspect.js:1958:40)
at formatWithOptions (internal/util/inspect.js:1842:10)
at Object.value (internal/console/constructor.js:306:14)
at Object.log (internal/console/constructor.js:341:61)
at C:\Myfiles\Reactjs\Projects\test-projects\routes\userRouter.js:243:37
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:4863:16
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\helpers\promiseOrCallback.js:16:11
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:4886:21
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:500:16
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:247:48
at next (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:168:27)
at next (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:170:9)
at Kareem.execPost (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:218:3) {
errors: {
password: ValidatorError: Path `password` is required.
at validate (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1256:13)
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1239:7
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1184:14)
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\document.js:2502:18
at processTicksAndRejections (internal/process/task_queues.js:75:11) {
properties: [Object],
kind: 'required',
path: 'password',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'user validation failed'
}
根据上面的尝试,代码无法加密密码,因此无法保存在mongodb中。我在对密码进行编码时做错了什么?
那么我该如何解决呢?
提前致谢
const passwordHash = bcrypt.hash(password, salt);
Here bcrypt.hash returning promise either your can use async/await or use .then().
userActivation = async (req, res) => {
const { token } = req.body;
if (token) {
jwt.verify(token, process.env.JWT_SECRET, function (err, decodeToken) {
if (err) {
return res.status(400).json({ error: "Incorrect or expired link." });
}
const { username, email, password, displayName } = decodeToken;
console.log(password);
User.findOne({ email }).exec((err, user) => {
if (user) {
return res.status(400).json({ error: "Username with this email exists." })
}
//Use genSaltSync when you donot want to use await or your can use await bcrypt.genSalt()
const salt = bcrypt.genSaltSync(10);
bcrypt.hash(password, salt, (err, passwordHash)=>{
const newUser = new User({
username,
email,
password: passwordHash,
displayName,
});
newUser.save((err, success) => {
if (err) {
console.log("Error in signup with account activation", err);
return res.status(400).json({ error: "Error activating account" });
}
res.json({
message: "signup Success!!",
});
})
})
})
})
}
}
Try this code once just put await before bcrypt and made function async.
我正在尝试通过 MERN 实施 jwt 身份验证,在 nodejs 中,我使用电子邮件激活 link 将用户电子邮件和密码保存在 mongodb 中。这是我注册用户和激活用户的工作示例。我正在使用 sendgrid 发送电子邮件。
//for email verification test
signup = async (req, res) => {
const { username, email, password, passwordCheck, displayName } = req.body;
//validate
if (!username || !email || !password || !passwordCheck)
return res.status(400).json({
msg: "not all fields have been entered.",
});
if (password.length < 8)
return res.status(400).json({
msg: "The password needs to be at least 8 characters long.",
});
if (password !== passwordCheck)
return res
.status(400)
.json({ msg: "Enter the same password twice for verification." });
const existingUser = await User.findOne({ email: email });
if (existingUser)
return res
.status(400)
.json({ msg: "An account with this email already exists." });
const existingUserName = await User.findOne({ username: username });
if (existingUserName)
return res
.status(400)
.json({ msg: "An account with this username already exists." });
if (!displayName) displayName = email;
const token = jwt.sign(
{ username, email, password, passwordCheck, displayName },
process.env.JWT_SECRET,{expiresIn:'1000m'}
);
const msg = {
to: email, //receiver's email
from: "no-reply@test.com", // Change to your verified sender
subject: `Email verification link ${displayName}`,
text: "testing from local",
html: `<h2>Hi ${displayName}</h2> <br/>sends a message for verification test: http://localhost:3000/authentication/activate/${token}</p> <br/><p>Have a nice day</p>`,
};
sgMail.setApiKey(process.env.SENDGRID_SECRET_API);
sgMail
.send(msg)
.then((result) => {
res.json({ message: "Email activation link has been sent" });
})
.catch((error) => {
console.error(error);
res.status(500).json("Error");
});
}
router.post("/register", signup);
userActivation = (req, res)=>{
const { token } = req.body;
if(token){
jwt.verify(token, process.env.JWT_SECRET,function(err,decodeToken){
if(err){
return res.status(400).json({error:'Incorrect or expired link.'})
}
const { username, email, password, passwordCheck, displayName }=decodeToken;
const newUser = new User({
username,
email,
password,
displayName,
});
newUser.save((err,success)=>{
if(err){
console.log("Error in signup with account activation",err)
return res.status(400).json({error:"Error activating account"})
}
res.json({
message:"signup Success!!"
})
});
} );
} else{
return res.json({error:"Something went wrong"})
}
}
router.post("/email-activate",userActivation)
在使用 postman 保存用户和激活密钥时,在 mongodb 中密码以纯文本形式保存。由于安全问题,我不希望它以纯文本形式保存。我希望它以加密方式保存并尝试使用以下代码:
userActivation = async (req, res) => {
const { token } = req.body;
if (token) {
jwt.verify(token, process.env.JWT_SECRET, function (err, decodeToken) {
if (err) {
return res.status(400).json({ error: "Incorrect or expired link." });
}
const { username, email, password, displayName } = decodeToken;
console.log(password)
User.findOne({ email }).exec((err, user) => {
if (user) {
return res.status(400).json({ error: "Username with this email exists." })
}
const salt = bcrypt.genSalt();
bcrypt.hash(password, salt, (err, passwordHash)=>{
const newUser = new User({
username,
email,
password: passwordHash,
displayName,
});
console.log(password)
console.log(passwordHash)
newUser.save((err, success) => {
if (err) {
console.log("Error in signup with account activation", err);
return res.status(400).json({ error: "Error activating account" });
}
res.json({
message: "signup Success!!",
});
})
})
})
})
}
}
当我启动我的服务器并尝试通过 postman 使用激活密钥登录时,它向我发送了一个激活 link。当我尝试通过激活中的 postman 发送 post 请求时 link,postman 显示 404 状态“错误激活帐户”并且节点索引显示以下错误:
The server has started on port: 5000
MongoDB connected
**the real password is showing undecoded**
**the real password is showing undecoded**
undefined
Error in signup with account activation Error: user validation failed: password: Path `password` is required.
at ValidationError.inspect (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\error\validation.js:47:26)
at formatValue (internal/util/inspect.js:731:31)
at inspect (internal/util/inspect.js:295:10)
at formatWithOptionsInternal (internal/util/inspect.js:1958:40)
at formatWithOptions (internal/util/inspect.js:1842:10)
at Object.value (internal/console/constructor.js:306:14)
at Object.log (internal/console/constructor.js:341:61)
at C:\Myfiles\Reactjs\Projects\test-projects\routes\userRouter.js:243:37
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:4863:16
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\helpers\promiseOrCallback.js:16:11
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:4886:21
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:500:16
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:247:48
at next (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:168:27)
at next (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:170:9)
at Kareem.execPost (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:218:3) {
errors: {
password: ValidatorError: Path `password` is required.
at validate (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1256:13)
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1239:7
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1184:14)
at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\document.js:2502:18
at processTicksAndRejections (internal/process/task_queues.js:75:11) {
properties: [Object],
kind: 'required',
path: 'password',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'user validation failed'
}
根据上面的尝试,代码无法加密密码,因此无法保存在mongodb中。我在对密码进行编码时做错了什么? 那么我该如何解决呢?
提前致谢
const passwordHash = bcrypt.hash(password, salt);
Here bcrypt.hash returning promise either your can use async/await or use .then().
userActivation = async (req, res) => {
const { token } = req.body;
if (token) {
jwt.verify(token, process.env.JWT_SECRET, function (err, decodeToken) {
if (err) {
return res.status(400).json({ error: "Incorrect or expired link." });
}
const { username, email, password, displayName } = decodeToken;
console.log(password);
User.findOne({ email }).exec((err, user) => {
if (user) {
return res.status(400).json({ error: "Username with this email exists." })
}
//Use genSaltSync when you donot want to use await or your can use await bcrypt.genSalt()
const salt = bcrypt.genSaltSync(10);
bcrypt.hash(password, salt, (err, passwordHash)=>{
const newUser = new User({
username,
email,
password: passwordHash,
displayName,
});
newUser.save((err, success) => {
if (err) {
console.log("Error in signup with account activation", err);
return res.status(400).json({ error: "Error activating account" });
}
res.json({
message: "signup Success!!",
});
})
})
})
})
}
}
Try this code once just put await before bcrypt and made function async.