Python Flask中check_password_hash始终返回false问题排查
Flask登录模块check_password_hash始终返回False问题修复
问题表现
使用Python Flask框架开发用户登录模块时,调用check_password_hash方法校验用户提交密码与数据库存储的哈希值始终返回False,密码校验流程无法正常通过,原有实现代码如下:
if request.method == "POST": email = request.form['email'] password = request.form['password'] cursor=mysql.connect.cursor() row = cursor.execute('SELECT * FROM login WHERE email = %s',[email]) if row>0: row2= cursor.execute('SELECT password FROM login WHERE email = %s', [email]) row2 = cursor.fetchall() cursor.close() if check_password_hash(row2[0][0],password): return('index.html') cursor.close()
常见原因
- 数据库
password字段长度不足,Werkzeug生成的密码哈希长度通常在100位以上,若字段设置为VARCHAR(50)之类的短长度,存入时哈希值被截断,校验必然失败。 - 注册存储密码时未使用配套的
generate_password_hash方法生成哈希,而是用了自定义的md5、sha1等其他算法生成密文存储,和校验方法不匹配。 - 从数据库取出的哈希值为bytes类型,未做字符串解码直接传入校验方法,类型不匹配导致返回False。
- 传参顺序错误,
check_password_hash要求第一个参数传入数据库存储的哈希值,第二个参数传入用户提交的明文密码,写反顺序会一直返回False。 - 原有代码存在逻辑冗余和bug:重复执行两次SQL查询、单条用户记录误用
fetchall取数、分支内关闭游标后外部重复调用cursor.close()会触发异常、直接返回字符串'index.html'无法正常渲染模板。
修复方案
- 先调整数据库表结构,将
password字段类型设置为VARCHAR(255),确保哈希值能完整存储,同时清理掉之前被截断的错误哈希数据,重新走注册流程生成正确的哈希存入。 - 替换原有登录逻辑代码,参考实现如下:
if request.method == "POST": email = request.form['email'] password = request.form['password'] cursor = mysql.connect.cursor() # 单次查询即可拿到需要的密码哈希,避免重复执行SQL cursor.execute('SELECT password FROM login WHERE email = %s', [email]) # 单条匹配记录用fetchone取数,性能更高 user_record = cursor.fetchone() cursor.close() if user_record: db_pwd_hash = user_record[0] # 兼容字节类型的哈希值,统一转成字符串再校验 if isinstance(db_pwd_hash, bytes): db_pwd_hash = db_pwd_hash.decode('utf-8') # 严格按照参数顺序传值:第一个是库中哈希,第二个是用户提交的明文 if check_password_hash(db_pwd_hash, password): # 用render_template渲染模板,不要直接返回字符串 return render_template('index.html') # 补全校验失败的分支逻辑 return "账号或密码错误"
- 确认注册逻辑的密码存储代码,必须使用如下方式生成哈希再入库,不能自定义加密逻辑:
# 注册时拿到用户明文密码后,生成哈希再存数据库 pwd_hash = generate_password_hash(用户提交的明文密码) # 执行SQL把pwd_hash存入login表的password字段
内容的提问来源于stack exchange,提问作者Micah
相关产品推荐
相关产品推荐

