[英]Login User using NodeJs from MySQL after password has been hashed using dcrypt
[英]User verification changing 'registered user hashed password', preventing login
用戶使用 bcrypt 散列密碼注冊。 通過mailtrap / nodemailer進行email驗證並成功驗證用戶狀態為true后,登錄失敗,返回“密碼不匹配”,因為它正在更改存儲的用戶哈希密碼。如果我跳過驗證步驟並直接登錄,它將工作正常 那么如何在不更改下面代碼中存儲的哈希密碼的情況下進行“用戶驗證”?
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, email, password, } 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, email, password: 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用戶MODEL:
@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,請不要考慮我的最后一個答案,我很困惑,概率與令牌無關。
但是我在創建用戶時總是使用相同的庫來加密密碼,位於用戶 model 上:
hashPassword() { this.password = bcrypt.hashSync(this.password, 8); }
在用戶 controller 中:
console.log(user.password) -> plain typed password await userRepository.save(user); console.log(user.password) -> encrypted password
如果我注冊一個驗證狀態為“true”的新用戶,它將毫無問題地登錄......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.