为什么在这个登录视图中check_password_hash总是返回False? [英] Why is check_password_hash always returning False in this login view?
问题描述
我有一个用户模型,使用Werkzeug的 set_password_hash
和 check_password_hash
函数设置和检查密码。 / p>
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 =用户名
self.set_password(密码)
$ b $ 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 [用户名']
passwd = flask.request.form ['passwd']
user = User.query.filter_by(username = username).first()
flask.flash(user.check_password(user.password))
如果user和user.check_password(user.password):
flask.session ['username'] = username
else:
flask.flash(User does not exist or密码是inccorect)
返回flask.render_template('login.html')
返回flask.render_template('index.html')
check_password
的闪现结果总是为False。我在做什么错了?
您已经定义了 User.password
长度为15,但密码哈希长度超过15个字符。所以当你稍后进行比较时,它不会是相同的值,它将被截断。
解决方案是定义更长的长度以适应长度或者使用一个不关心长度的数据库(PostgreSQL,SQLite),并且根本不需要设置列的长度(这是可取的)。
password = db.Column(db.String)#no length
#or
password = db.Column(db.String(255))#some还有另外一个问题:你们有一些问题,比如:使用存储的散列重新调用 check_password
,而不是使用用户输入。
#wrong
user.check_password(user.password)
#应该是
user.check_password(passwd)
以下是一个小例子,演示密码正常工作。 $ p> 从sqlalchemy.ext.declarati导入sqlalchemy作为sa
从sqlalchemy.orm导入declarative_base
从werkzeug.security导入Session
import generate_password_hash,check_password_hash
$ b $ engine = sa.create_engine('sqlite://',echo = True)
session = Session(引擎)
Base = declarative_base(引擎)
class用户(Base):
__tablename__ ='user'
$ b $
username = sa.Column(sa.String,nullable = False,unique = True)
password = sa.Column('password' ,sa.String)
$ b $ def set_password(self,secret):
self.password = generate_password_hash(secret)
$ b $ def check_password(self,secret):
返回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')。一()
打印(上密码)
#pbkdf2:sha1:1000 $ w9jx4Egp $ b420d784ac6ad0575e4a9a908bb4679826e56f5f
print(u.check_password('cabbage'))
#True
pre>
I have a user model with functions to set and check a password using Werkzeug's set_password_hash
and check_password_hash
functions.
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')
The flashed result of check_password
is always "False". What am I doing wrong?
解决方案 You've defined User.password
to have a length of 15, but the password hash is longer than 15 characters. So when you go to compare it later, it will not be the same value, it will be truncated.
The solution is to either define a longer length to accommodate the length of the hash, or use a database that doesn't care about length (PostgreSQL, SQLite) and don't set a length for the column at all (this is preferable).
password = db.Column(db.String) # no length
# or
password = db.Column(db.String(255)) # some longer length
There's also a second problem: you're calling check_password
with the stored hash, not with the user input.
# wrong
user.check_password(user.password)
# should be
user.check_password(passwd)
The following is a small example that demonstrates the password working correctly.
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
这篇关于为什么在这个登录视图中check_password_hash总是返回False?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!