[英]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.