Flask AttributeError: невозможно установить атрибут - PullRequest
0 голосов
/ 09 октября 2018

Я делаю проект на флаконе Python, когда я создал базу данных с помощью sqlite, база данных создается, и в нее вставляется значение, но когда я перезапускаю свой проект и пытаюсь вставить значения в базу данных через консоль python, как

from app import db
from app import Credentials as C
c= C(fname="John", lname="Doe", username="johndoe", email="john@doe.com", password="11111111")

Я получил такую ​​ошибку

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<string>", line 4, in __init__
  File "C:\Users\Lenovo\PycharmProjects\FlaskProject\venv\lib\site-packages\sqlalchemy\orm\state.py", line 417, in _initialize_instance
    manager.dispatch.init_failure(self, args, kwargs)
  File "C:\Users\Lenovo\PycharmProjects\FlaskProject\venv\lib\site-packages\sqlalchemy\util\langhelpers.py", line 66, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "C:\Users\Lenovo\PycharmProjects\FlaskProject\venv\lib\site-packages\sqlalchemy\util\compat.py", line 249, in reraise
    raise value
  File "C:\Users\Lenovo\PycharmProjects\FlaskProject\venv\lib\site-packages\sqlalchemy\orm\state.py", line 414, in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "C:\Users\Lenovo\PycharmProjects\FlaskProject\venv\lib\site-packages\sqlalchemy\ext\declarative\base.py", line 700, in _declarative_constructor
    setattr(self, k, kwargs[k])
AttributeError: can't set attribute

Помогите мне исправить ошибку Я использую все последние версии библиотек

Вот мое определение модели:

class Credentials(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    fname = db.Column(db.String(32), nullable=False)
    lname = db.Column(db.String(32))
    username = db.Column(db.String(16), unique=True, nullable=False)
    email = db.Column(db.String(64), unique=True, nullable=False)
    password = db.Column(db.String(100))
    date_created = db.Column(db.DateTime, default=datetime.utcnow)

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    def __repr__(self):
        return f"Users('{self.fname}','{self.email}','{self.username}')"

1 Ответ

0 голосов
/ 09 октября 2018

Ваша ошибка вызвана определением свойства password:

@property
def password(self):
    raise AttributeError('password is not a readable attribute')

Это заменило предыдущее определение для имени password объектом свойства без установщика.Вы можете воспроизвести проблему с помощью

>>> class Foo:
...     @property
...     def bar(self):
...         raise AttributeError('bar is not a readable attribute')
...
>>> f = Foo()
>>> f.bar = 'new value'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

Свойства не имеют установщиков, если вы не указали их явно, а свойства - это просто больше объектов в пространстве имен класса, вы не можете использовать одно и то же имя для определения столбцаи свойство.

Вы можете просто переименовать столбец, например, в _password, но здесь есть большая проблема: Вы никогда не должны хранить пароли пользователей в своей базе данных .

Вместо этого вы должны хранить пароль хэшей , сгенерированные криптографически уникальные строки, которые могут быть воспроизведены только в том случае, если в будущем ваша программа будет представлена ​​с тем же паролем.Таким образом, вы можете проверить , что кто-то все еще знает правильный пароль, не давая хакерам доступа к паролям, если им удастся украсть вашу базу данных.

Очень важно, чтобывы никогда не предоставляете хакерам доступ к паролям .См. этот анализ нарушения безопасности в Adobe , чтобы узнать, почему вы никогда не захотите оказаться в такой же ситуации.Моя учетная запись была взломана и в этом хакере, но только потому, что я использую уникальные пароли для каждого сайта, хакеры не смогли повторно использовать информацию моей учетной записи для доступа к другим сайтам.

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

Здесь должно быть достаточно использовать пакет werkzeug.security :

from sqlalchemy.ext.hybrid import hybrid_property
from werkzeug.security import generate_password_hash, check_password_hash

class Credentials(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    fname = db.Column(db.String(32), nullable=False)
    lname = db.Column(db.String(32))
    username = db.Column(db.String(16), unique=True, nullable=False)
    email = db.Column(db.String(64), unique=True, nullable=False)
    date_created = db.Column(db.DateTime, default=datetime.utcnow)

    _password_hash = db.Column('password', db.String(100))

    @hybrid_property
    def password(self):
        return self._password_hash

    @password.setter
    def _set_password(self, plaintext):
        self._password_hash = generate_password_hash(plaintext)

    def validate_password(self, password):
        return check_password_hash(self._password_hash, password)

    def __repr__(self):
        return f"Users('{self.fname}', '{self.email}', '{self.username}')"

Я использовал Объект гибридного свойства SQLAlchemy для обработки атрибута password здесь.Обратите внимание, что столбец хранится в _password (но столбец базы данных по-прежнему называется password) и что значение автоматически хешируется при его установке.

Затем можнопроверять пароли по хешу, сохраненному в базе данных, с помощью метода check_password().

Реализация werkzeug.security защищает от временных атак (где злоумышленник может сработать, если он близок к правильному паролю, измеряя, как долго ониспользует ваш сервер для проверки паролей), но слабее в том, что поддерживает устаревшие протоколы.Другие пакеты, такие как Flask-BCrypt, позволяют настраивать более строгие политики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...