如何解决用户验证更改“注册用户散列密码”,阻止登录
用户使用 bcrypt 散列密码注册。通过mailtrap/nodemailer进行邮件验证并成功验证用户状态为true后,登录失败,返回“unmatched password”,因为它正在更改存储的用户散列密码。如果我跳过验证步骤并直接进行登录,它将工作正常。那么如何在不更改下面代码中存储的散列密码的情况下进行“用户验证”?
async login(req: Request,res: Response){
// Get user from database
const userRepository = getRepository(User);
const { email,password } = req.body;
if (!(email && password)) {
console.error('Empty name or password!');
return res.status(400).send({
error: 'Empty name or password'
});
}
const user = await userRepository.findOne({ where: { email } });
let storedUserPass = user!.password;
console.log(password) //-> consoles plain typed text
console.log(storedUserPass) //-> consoles encrypted password
const isValidPassword = await bcrypt.compareSync(password,storedUserPass as string);
console.log(isValidPassword) //-> consoles false
if(!user) {
return res.send(`User doesn t exist! `);
}
else if (!user.isverified) {
return res.send('Your Email has not been verified. Please do so!');
}
else if(!isValidPassword) {
return res.send('Password doesn t match')
}
else {
// Sing JWT,valid for 1 hour
const token = jwt.sign(
{ id: user.id,email: user.email },process.env.NODE_ENV,{ expiresIn: "1d" }
);
res.json({
user,token
});
}
},
async create(req: Request,res: Response) {
const verificationToken = await crypto.randomBytes(8).toString('hex');
const { name,email,password,role,isverified } = req.body;
const date = new Date();
try {
const userRepository = getRepository(User);
const tokenRepository = getRepository(Token);
//User validation
const data = {
name,}
const schema = Yup.object().shape({
name: Yup.string().required('Name required.').max(60),email: Yup.string().email("Invalid Email.").required(),password: Yup.string().required().min(4).max(10),})
await schema.validate(data,{
abortEarly: false
});
const userExists = await userRepository.findOne({ where: { email }})
if(userExists) {
return res.send(`Usuário com email cadasTrado ${email} já existe!` );
} else {
const token = tokenRepository.create({token: verificationToken,tokenDate: date})
await tokenRepository.save(token);
const user = userRepository.create({ name,role: role || "basic",isverified,date,token})
console.log(user.password) // consoles plain text
await userRepository.save(user);
console.log(user.password) //consoles encrypted text
return new Promise((resolve,reject)=>{
const transp = transport;
var mailOptions = {
from: 'AdminisTrador <c3e26a9df0-703049@inBox.mailtrap.io>',to: email,subject: 'Account verification link!',html: `<h2>Olá ${user.name}</h2><br/>
<p>Finalize o seu cadastro clicando neste <a href="http://${req.headers.host}/users/confirmation/${user.email}/${verificationToken}" target="_about" style="color: blue,text-derocation: none"}>Link</a>`
}
transp.sendMail(mailOptions,function(error: Err){
if (error) {
return res.status(500).send({msg:'Technical Issue!,Please click on resend for verify your Email.'});
}
else {
return res.send('A verification email has been sent to ' + user.email + '. It will be expire after one day. If you not get verification Email click on resend token.');
});
})
}
} catch(err) {
return res.status(404).send({ err: "Failed to send email."})
}
},
//TYPEORM 用户模型:
@Entity('users')
export default class User {
@PrimaryGeneratedColumn('uuid')
id: number;
@Column()
name: string;
@Column({
unique: true
})
email: string;
@Column()
password: string;
@Column()
role: string;
default: 'basic'
enum: ["basic","supervisor","admin"];
@Column({
type: "datetime"
})
date!: Date;
@Column({
default: false
})
isverified: boolean;
@BeforeInsert()
@BeforeUpdate()
hashPassword() {
this.password = bcrypt.hashSync(this.password,8); // salt de 8
}
checkIfUnencryptedPasswordisValid(unencryptedPassword: string) {
return bcrypt.compareSync(unencryptedPassword,this.password);
}
@OnetoMany(() => Orphanage,orphanage => orphanage.user,{
cascade: ['insert','update']
})
@JoinColumn({ name: 'user_id'})
orphanages: Orphanage[];
@OnetoOne(type => Token)
@JoinColumn()
token: Token;
}
async confirmEmail(req: Request,res: Response) {
try {
const userRepository = getRepository(User);
const tokenRepository = getRepository(Token);
const tokenExists = await tokenRepository.findOne({ token: req.params.token });
tokenExists!.tokenDate
if( !tokenExists ) {
return res.status(400).send({msg:'Your verification link may have expired. Please click on resend for verify your Email.'});
} else {
const user = await userRepository.findOne({where: { token: tokenExists,email: req.params.email }})
//user not exist
if(!user) {
return res.status(401).send({msg:'We were unable to find a user for this verification. Please SignUp!'});
} // user is already verified
else if (user.isverified){
return res.status(200).send('User has been already verified. Please Login');
} else { //verify user
user.isverified = true;
await userRepository.save(user);
console.log(user) // -> hashed user.password is different from when created user after user is verified.
return res.status(200).send('Your account has been successfully verified')
}
}
} catch(err) {
return res.status(500).send({err: "Sorry,it Could not be validated!"});
}
},
解决方法
在 ?
中使用 user?.password
不是一种有效的方式。符号?
用于三元运算符。三元运算符需要三个参数,而您没有提供这些参数。
解决方案:如下所示格式化您的代码。我在 !
中使用了 user!.password
运算符。 user!
中的此运算符可确保您的转译器不会未定义用户。因此,在使用此运算符之前,您应该检查是否定义了用户,如下所示:
if(!user) {
return res.send(`User doesn t exist! `);
}
如果您在使用 !
之前不检查用户,您可能会在未定义用户的情况下收到运行时错误。无需使用 as string
。
更改代码中的块:
const user = await userRepository.findOne({ where: { email } });
//check user immediately after getting it to avoid errors
if(!user) {
return res.send(`User doesn t exist! `);
}
let storedUserPass = user!.password;
const isValidPassword = await bcrypt.compareSync(password,storedUserPass);
现在您的代码将如下所示:
async login(req: Request,res: Response){
// Get user from database
const userRepository = getRepository(User);
const { email,password } = req.body;
if (!(email && password)) {
console.error('Empty name or password!');
return res.status(400).send({
error: 'Empty name or password'
});
}
const user = await userRepository.findOne({ where: { email } });
if(!user) {
return res.send(`User doesn t exist! `);
}
let storedUserPass = user!.password;
const isValidPassword = await bcrypt.compareSync(password,storedUserPass);
if (!user.isVerified) {
return res.send('Your Email has not been verified. Please do so!');
}
else if(!isValidPassword) {
return res.send('Password doesn t match')
}
else {
// Sing JWT,valid for 1 hour
const token = jwt.sign(
{ id: user.id,email: user.email },process.env.NODE_ENV,{ expiresIn: "1d" }
);
res.json({
user,token
});
}
}
,
Shakir Aqeel,请不要考虑我最后的答案,我很困惑,概率与令牌无关。
但我在创建用户时总是使用相同的库来加密密码,位于用户模型:
hashPassword() {
this.password = bcrypt.hashSync(this.password,8);
}
在用户控制器中:
console.log(user.password) -> plain typed password
await userRepository.save(user);
console.log(user.password) -> encrypted password
如果我注册一个验证状态为“true”的新用户,它会登录没有问题....
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。