简体   繁体   English

Flask中没有哈希密码

[英]Not hashing password in Flask

I don't know why the password is not hashing using Bcrypt. 我不知道为什么密码不使用Bcrypt散列。 I think I am doing it right. 我想我做对了。 I initilized Bcrypt correctly and I am using mongoengine. 我正确地启动了Bcrypt,我使用的是mongoengine。 Everytime I look at the database it still shows the unencrypyed passwrod in text. 每当我查看数据库时,它仍然会在文本中显示未加密的密码。

users/models.py 用户/ models.py

from app import db, bcrypt
class User(db.Document):

    username = db.StringField(required=True)
    first_name = db.StringField(required=True)
    last_name = db.StringField(required=True)
    email = db.EmailField(required=True)
    password = db.StringField(required=True)

    meta = {'collection': 'users'}

    @property
    def hash_password(self):
        return self.password

    @hash_password.setter
    def set_hash_password(self, password):
        self.password = bcrypt.generate_password_hash(password)

    def verify_password(self, password):
        return bcrypt.check_password_hash(self.password, password)

users/views.py 用户/ views.py

@userV.route('/signup', methods=['GET', 'POST'])
def signup():
    form = SignUpForm()

    if form.validate_on_submit():
        user = User(
            first_name=form.first_name.data,
            last_name=form.last_name.data,
            username=form.username.data,
            email=form.email.data,
            password=form.password.data
        ).save()

        flash('You can now login')
        return render_template('user.html', variable="You can now login " + user.username)

    return render_template('signup.html', form=form)

users/auth/forms.py 用户/认证/ forms.py

class SignUpForm(Form):
    username = StringField('Username', validators=[
        InputRequired(message="Username is required"),
        Regexp('^[A-Za-z][A-Za-z0-9_]*[A-Za-z0-9]$', 0, 'Usernames must have only letters, numbers or underscores')
    ])
    first_name = StringField('First Name', validators=[
        InputRequired(message="First name is required")
    ])
    last_name = StringField('Last Name', validators=[
        InputRequired(message="Last name is required")
    ])
    email = StringField('Email Address', validators=[
        InputRequired(message="Email is required"),
        Email(message="This is not a valid email")
    ])
    password = PasswordField('Password', validators=[
        InputRequired(message="Password is required"),
        Length(min=6, message="The password is not long enough")
    ])
    accept_tos = BooleanField('Accept Terms of Service', validators=[
        InputRequired(message="You have to accept the Terms of Service in order to use this site")
    ])
    submit = SubmitField('Signup')

    def validate(self):
        if not Form.validate(self):
            return False

        if User.objects(username=self.username.data).first():
            raise ValidationError('Username already in use')

        if User.objects(email=self.email.data).first():
            raise ValidationError('Email already registered')

        return True

This is the outcome when I search mongodb shell. 这是我搜索mongodb shell时的结果。 The password is not hashed. 密码未经过哈希处理。

{ "_id" : ObjectId("555df97deddd5543c360888a"), "username" : "FullMetal", "first_name" : "Edward", "last_name" : "Elric", "email" : "fullmetalalchemist@gmail.com", "password" : "equalexchange" }

The property is called hash_password not password . 该属性称为hash_password而不是password I don't see where hash_password is getting assigned (that's when its setter gets called). 我没有看到hash_password被分配的位置(即调用其setter时)。 Also your setter method should have exactly the same name as the property itself, in this case hash_password not ( set_hash_password ). 此外,您的setter方法应该与属性本身具有完全相同的名称,在本例中为hash_password not( set_hash_password )。 You can then do 然后你可以做

user = User(hash_password=form.password.data)

Unfortunately, due to the way mongoengine.Document.__init__ works, you wont be able to use your field this way. 不幸的是,由于mongoengine.Document.__init__工作方式,你将无法以这种方式使用你的领域。 You have two options to make it work: 您有两种方法可以使其工作:

Option 1: First create the User object without the password, then set the hash_password, then save 选项1:首先创建没有密码的User对象,然后设置hash_password,然后保存

user = User(first_name=form.first_name.data,
            last_name=form.last_name.data,
            username=form.username.data,
            email=form.email.data)
user.hash_password = form.password.data
user.save()

Option 2: Requires overriding the __init__ method for User 选项2:需要覆盖User__init__方法

class User(db.Document):
    def __init__(self, *args, **kwargs):
        if 'hash_password' in kwargs:
            self.hash_password = kwargs.pop('hash_password')
        super(User, self).__init__(*args, **kwargs)

Now you can use User as you initially wanted: 现在您可以按照您最初的需要使用用户:

user = User(first_name=form.first_name.data, hash_password=form.password.data)

Python @property decorator doesn't work with old-style classes. Python @property装饰器不适用于旧式类。 I made this demo - note the class inheriting from object , which makes it a new-style class. 我做了这个演示 - 注意继承自object的类,这使它成为一个新式的类。 Have a look and modify this to suit your need 看看并修改它以满足您的需要

class User(object):

    def __init__(self, username, first_name, last_name, email, password):
        print "Initializing"
        self.username = username
        self.first_name = first_name
        self.last_name = last_name
        self.email = email
        self.password = password

    @property
    def password(self):
        print "getting password"
        return self._password

    @password.setter
    def password(self, password):
        print "Setting password"
        self._password = bcrypt.generate_password_hash(password)

    def verify_password(self, password):
        return bcrypt.check_password_hash(self.password, password)

As I mentioned earlier, if all else fails, I'd solve this by performing the logic in my view. 正如我之前提到的,如果所有其他方法都失败了,我会通过在我的视图中执行逻辑来解决这个问题。 That's what I'd have done in the first place, tbh. 这就是我首先做的事情,tbh。 Python favors expressiveness. Python倾向于表达。 I have omitted the other parts 我省略了其他部分

user = User(password=bcrypt.generate_password_hash(form.password.data))

And just removing the @property setter and getter in the User class. 只需删除User类中的@property setter和getter。

Here is what I do in the same circumstances: 这是我在相同情况下所做的事情:

class User(db.Document):
    ...
    password = db.StringField(max_length=255, required=True)

    ...
    def set_password(self, password):
        self.password = bcrypt.generate_password_hash(password)
    ...

Then, in views.py I do the following: 然后,在views.py中,我执行以下操作:

user = User(..)
user.set_password(form.password.data)
user.save()

This way your logic stays within your model, but can be called easily from outside. 这样,您的逻辑就会停留在您的模型中,但可以从外部轻松调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM