我有一个用户模型,其中包含使用Werkzeug的set_password_hash
和check_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
的闪现结果总是"错误"。我做错了什么?
答案 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