微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用户验证更改“注册用户散列密码”,阻止登录

如何解决用户验证更改“注册用户散列密码”,阻止登录

用户使用 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 举报,一经查实,本站将立刻删除。