2015-05-21 2 views
2

Я не знаю, почему пароль не хешируется с помощью Bcrypt. Я думаю, что делаю все правильно. Я правильно инициализировал Bcrypt, и я использую mongoengine. Каждый раз, когда я смотрю на базу данных, он все еще показывает unencrypyed passwrod в тексте.Не хеширующий пароль в Flask

пользователей/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) 

пользователей/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) 

пользователей/аутентификации/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 

Это результат при поиске MongoDB оболочка. Пароль не хешируется.

{ "_id" : ObjectId("555df97deddd5543c360888a"), "username" : "FullMetal", "first_name" : "Edward", "last_name" : "Elric", "email" : "[email protected]", "password" : "equalexchange" } 
+1

Выполняется ли 'set_hash_password (self, password)' даже запуск? – sobolevn

ответ

0

Вот что я в одних и тех же обстоятельствах:

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

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

Тогда в views.py я делаю следующее:

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

Таким образом, ваша логика остается в вашей модели, но может быть легко вызываемый снаружи.

2

Python @property декоратор не работает с old-style классов. Я сделал эту демонстрацию - обратите внимание на класс, наследующий от object, что делает его классом нового стиля. Посмотрите и изменить это, чтобы удовлетворить вашу потребность

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) 

Как я уже говорил ранее, если все остальное терпит неудачу, я бы решить эту проблему, выполнив логику, на мой взгляд. Это то, что я сделал бы в первую очередь, тбх. Python выступает за выразительность. я опустил другие части

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

И только удаление в @property и присваивателя в User классе.

+0

Да. Я думал об этом, но я не пробовал. Я хочу, чтобы весь мой код был разделен даже на хэширование. Если я закончу этот маршрут, я бы проверял его как ответ. Я также пытаюсь узнать, как работают объекты @property. –

+0

Я попытался выполнить __init__ несколько раз перед рукой, и он всегда показывает мне ошибку 'AttributeError: _initialised' –

+0

Это странно. Я только что перепроверил его, и все получилось. Удостоверьтесь в правильности присвоения свойств - используйте «_» правильно. – Ladmerc

4

Недвижимость называется hash_password не password. Я не вижу, где назначается hash_password (тогда вызывается его сеттер). Также ваш метод установки должен иметь точно такое же имя, как и само свойство, в данном случае hash_password нет (set_hash_password). После этого вы можете сделать

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

К сожалению, из-за способа mongoengine.Document.__init__ работы, вы не сможете использовать поле таким образом. У вас есть два варианта, чтобы сделать его работу:

Вариант 1: Сначала создайте объект пользователя без пароля, а затем установите 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() 

Вариант 2: Требуется переопределение метода __init__ для User

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) 

Теперь вы можете использовать пользователя, как вы изначально хотели:

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

Я попытался переключить его на hash_password, но я получаю это 'mongoengine.errors.FieldDoesNotExist - FieldDoesNotExist: поле« hash_password »не существует в документе« Пользователь » –

+0

К сожалению, из-за способа mongoengine.Document .__ init __() работает , вы не сможете использовать свое поле таким образом. См. Мое редактирование выше – junnytony

+0

Да, ваши две возможности не работают по какой-то причине. Это имеет смысл, и он должен работать, но по какой-то причине это не так. Я думаю, что это Mongoengine, потому что я вижу другой код, используя этот точный метод. –

Смежные вопросы