为什么check_password_hash在此登录视图中始终返回False?

时间:2015-04-23 17:16:45

标签: python hash flask

我有一个用户模型,其中包含使用Werkzeug的set_password_hashcheck_password_hash函数设置和检查密码的功能。

models.py

class User(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    username = db.Column(db.String(15), unique = True)
    password = db.Column(db.String(15))
    tasks = db.relationship('Task', backref='author', lazy='dynamic')

    def __init__(self, username, password):
        self.username = username
        self.set_password(password)

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

    def check_password(self, password):
        return check_password_hash(self.password, password)

login.py

def post(self): 
    username = flask.request.form['username']
    passwd = flask.request.form['passwd']
    user = User.query.filter_by(username = username).first()
    flask.flash(user.check_password(user.password))
    if user and user.check_password(user.password):
        flask.session['username'] = username
    else:
        flask.flash("User doesn't exist or password is inccorect.")
        return flask.render_template('login.html')
    return flask.render_template('index.html')

check_password的闪现结果总是"错误"。我做错了什么?

1 个答案:

答案 0 :(得分:2)

您已将User.password定义为长度为15,但密码哈希值超过15个字符。因此,当您稍后进行比较时,它将不会是相同的值,它将被截断。

解决方案是定义更长的长度以适应散列的长度,或者使用不关心长度的数据库(PostgreSQL,SQLite)并且根本不设置列的长度(这个是优选的。)

password = db.Column(db.String)  # no length
# or
password = db.Column(db.String(255))  # some longer length

还有第二个问题:您使用存储的哈希调用check_password,而不是使用用户输入。

# wrong
user.check_password(user.password)
# should be
user.check_password(passwd)

以下是演示密码正常工作的小例子。

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from werkzeug.security import generate_password_hash, check_password_hash

engine = sa.create_engine('sqlite://', echo=True)
session = Session(engine)
Base = declarative_base(engine)

class User(Base):
    __tablename__ = 'user'

    id = sa.Column(sa.Integer, primary_key=True)
    username = sa.Column(sa.String, nullable=False, unique=True)
    password = sa.Column('password', sa.String)

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

    def check_password(self, secret):
        return check_password_hash(self.password, secret)

Base.metadata.create_all()

u = User(username='davidism')
u.set_password('cabbage')
session.add(u)
session.commit()

u = session.query(User).filter_by(username='davidism').one()
print(u.password)
# pbkdf2:sha1:1000$w9jx4Egp$b420d784ac6ad0575e4a9a908bb4679826e56f5f
print(u.check_password('cabbage'))
# True