flask-bcrypt-ValueError: недопустимая соль


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

ValueError: Invalid salt

Models.py

class User(db.Model):

    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    email = db.Column(db.String, nullable=False)
    password = db.Column(db.String, nullable=False)
    posts = db.relationship("Post", backref="author", lazy="dynamic")

    def __init__(self, name, email, password):
        self.name = name
        self.email = email
        self.password = bcrypt.generate_password_hash(password)

    def __repr__(self):
        return '<User {}>'.format(self.name)

Views.py

@app.route("/login", methods=["GET", "POST"])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter(User.name == form.username.data).first()
        if user and bcrypt.check_password_hash(user.password, form.password.data):
            flash("you were just logged in!")
            login_user(user)
            return redirect(url_for("home"))
        else:
            flash("bad username or password")
    return render_template("login.html", form=form)

Forms.py

class LoginForm(Form):
    username = StringField('username', validators=[DataRequired()])
    password = PasswordField('password', validators=[DataRequired()])
9 8

9 ответов:

В основном вы хотели бы закодировать свои данные перед хэшем: пароль.кодирование ('utf-8'). Если он приходит как unicode, это может вызвать ошибки. Взгляните также сюда: https://github.com/maxcountryman/flask-bcrypt/issues/9

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

Из источника bcrypt для hashpw():

hashed = _bcrypt.ffi.new("unsigned char[]", 128)
retval = _bcrypt.lib.crypt_rn(password, salt, hashed, len(hashed))

if not retval:
    raise ValueError("Invalid salt")

Пакет bcrypt (который Flask-Bcrypt использует для выполнения работы) возвращает ValueError: Invalid salt всякий раз, когда вызов bcrypt lib операционной системы возвращает ошибку. Поэтому, если по какой-то причине он вообще не может вызвать bcrypt lib, он все равно (неправильно) вернет ошибку Invalid salt.

Похоже, это недостаток в пакете bcrypt реализация-она должна проверять конкретные значения retval.


В моем случае ошибка оказалась связанной с запуском Flask под Apache mod_wsgi в virtualenv. Я мог бы запустить flask напрямую без проблем (используя flask-cli), но точно такой же экземпляр приложения не будет успешно использовать bcrypt при запуске под mod_wsgi.

Проблема была решена путем изменения конфигурации моего Apache для использования virtualenv в качестве основной среды Python для mod_wsgi.

В httpd.conf или под /etc/httpd/conf.d/... добавить:

WSGIPythonHome /path/to/my/application-virtualenv

Дополнительную информацию об этой конфигурации можно найти здесь: Virtual Environments-mod_wsgi documentation

Я все еще подозреваю, что моя конкретная проблема связана с чем-то, что затеняется сайтпакетами python моей системы, или с чем-то еще, связанным с python includes.


Edit: установка WSGIPythonHome оказалась не для решения проблемы. В конце концов я переключился наuWSGI сnginx .

В моем случае проблема была связана с преобразованием типа, происходящим во время хранения пароля. Использование bcrypt.generate_password_hash(plaintext) возвращает двоичное значение, например b'$2b$12$zf/TxXZ4JJZ/lFX/BWALaeo0M.wNXrQXLqIFjmZ0WebqfVo9NES56'.

Как и у меня, ваш столбец пароля настроен в виде строки:

password = db.Column(db.String, nullable=False)

Я обнаружил, что генерация хэша выше, хранение этого двоичного значения в моем столбце string password, а затем просто получение его привело к другому значению из - за преобразования типа SQLAlchemy-ничего общего с bcrypt вообще!

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

password = db.Column(db.Binary(60), nullable=False)

Я не знаю наверняка, но предполагаю, что различные производственные среды и базы данных могут обрабатывать преобразование этого типа по-разному (обратимо в некоторых случаях, а не в других), возможно, объясняя смешанный успех @Samuel Jaeschke.

Это также объясняет, почему кодирование входной строки в ограниченный символ set (более раннее решение) может помочь в некоторых случаях, но не в других - если это приведет к преобразованию типа to/from, то вы восстановите правильный хэш из базы данных для сравнения.

Во всяком случае, это решило для меня эту проблему.

Моя проблема похожа на описанную @tomClark

Я использую Postgres как мой DDBB и его драйвер , или систему DDBB, кодирующую Всегда уже закодированную строку. Второй процесс кодирования создает недопустимый хэш следующим образом:
'\\x24326224313224483352757749766438764134333757365142464f4f4f464959664d66673575‌​467873754e466250716f3166375753696955556b2e36'

Правильный хэш выглядит так:

$2b$12$Wh/sgyuhro5ofqy2.5znc.35AjHwTTZzabz.uUOya8ChDpdwvROnm

Чтобы разрешить его, я декодирую хэш в utf8, чем сохраняю его в DDBB.

Пример кода:

def set_password(self, pw):
    pwhash = bcrypt.hashpw(pw.encode('utf8'), bcrypt.gensalt())
    self.password_hash = pwhash.decode('utf8') # decode the hash to prevent is encoded twice

Вам нужно применить .decode('utf-8') к вашему self.password:

def set_password(self, password):
    """Set password."""
    self.password = bcrypt.generate_password_hash(password).decode('utf-8')

Я верю, что вы используете Python 3 и bcrypt0.7.1. сначала вы должны удалить пользователей из вашей базы данных, а затем перейти к вашим моделям и добавить .декодируйте ('utf-8') в метод generate_password_hash () следующим образом:

pw_hash = bcrypt.generate_password_hash(‘hunter2’).decode('utf-8')

В качестве альтернативы вы можете удалить flask-bcrypt==0.7.1 и установить flask-bcrypt==0.62. Убедитесь, что вы удалить пользователей из таблицы перед установкой колбу-осуществляется==0.62

У меня была похожая проблема. Мой код для проверки пароля был следующим:

if check_password_hash(form.password.data, user.pw_hashed):

Когда я изменил порядок на:

if check_password_hash(user.pw_hashed, form.password.data):

Это сработало хорошо.

Вам совершенно не нужно flask-bcrypt для использования bcrypt.

Просто сделайте что-нибудь вроде этого:

class User(Base):
    _password = db.Column("password", db.String, nullable=False)

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

    @password.setter
    def password(self, value):
        bvalue = bytes(value, 'utf-8')
        temp_hash = bcrypt.hashpw(bvalue, bcrypt.gensalt())
        self._password = temp_hash.decode('utf-8')

    def check_password(self, value):
        return bcrypt.checkpw(value.encode('utf-8'), self._password.encode('utf-8'))

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