使用Werkzeug的密码哈希验证函数验证密码失败求助
问题:登录验证密码始终验证失败
我开发了一个简单的用户登录验证应用,并编写了密码测试脚本,但测试用例始终验证失败。以下是相关代码:
Python 后端代码
# Validate Form if form.validate_on_submit(): email = form.email.data password = form.password_hash.data password_hash = generate_password_hash("password", "sha256") # Clear the form form.email.data = '' form.password_hash.data = '' # Lookup User Password by email pw_to_check = get_user_pwd(email) # this gets the DB password (hashed) # Check Hashed Password passed = check_password_hash(pw_to_check, password) return render_template("test_pw.html", email = email, password = password, pw_to_check = pw_to_check, password_hash =password_hash, passed = passed, form = form) def get_user_pwd(email): # this function gets the user password by email with connection: with connection.cursor() as cursor: password_hash = "NONE" cursor.execute("SELECT password_hash FROM users WHERE email=email;") password_hash = cursor.fetchone()[0] return password_hash
HTML 模板代码
{% if email %} <h1>Email: {{ email }}</h1> <h1>Password: {{ password }}</h1> <br/> <h2>I found this info:</h2> <br/> Email: {{email}}<br/> PW in DB (hash): {{pw_to_check}}<br/> PW in form (hash): {{password_hash}}<br/> <br/> Passed: {{ passed }} {% else %} <h1>What's Your Email and Password?</h1> <br/> <form method="POST"> {{ form.hidden_tag() }} {{ form.email.label(class="form-label") }} {{ form.email(class="form-control") }} <br/> {{ form.password_hash.label(class="form-label") }} {{ form.password_hash(class="form-control") }} <br/> {{ form.submit(class="btn btn-secondary") }} </form> {% endif %}
执行passed = check_password_hash(pw_to_check, password)语句后,结果始终为false。我已确认以下几点:
- 数据库中存储的密码哈希是通过
generate_password_hash("password12345", "sha256")生成的; - 登录表单中输入的密码为password12345,与生成哈希的密码完全一致;
- 已参考类似问题,通过
cursor.fetchone()[0]避免了将元组传入check_password_hash的问题。
请问我哪里出错了?希望能得到帮助。
问题排查与解决
核心错误出在get_user_pwd函数的SQL查询语句上:
原语句SELECT password_hash FROM users WHERE email=email;中,数据库会将email=email解析为字段email等于自身,这对所有非NULL的email记录都成立,因此你获取到的pw_to_check并不是对应输入邮箱的用户密码哈希,而是数据库中第一条满足条件的用户哈希,自然和输入的密码不匹配,导致check_password_hash返回False。
修复方案
修改get_user_pwd函数,使用参数化查询传递邮箱参数,同时增加查询结果的空值判断:
def get_user_pwd(email): # this function gets the user password by email with connection: with connection.cursor() as cursor: password_hash = "NONE" # 使用参数化查询(%s为MySQL占位符,SQLite需改为?,根据你的数据库类型调整) cursor.execute("SELECT password_hash FROM users WHERE email=%s;", (email,)) result = cursor.fetchone() # 避免查询不到用户时抛出索引错误 if result: password_hash = result[0] return password_hash
额外优化建议
- 移除或调整无关代码:原代码中
password_hash = generate_password_hash("password", "sha256")是硬编码生成固定密码的哈希,和当前登录验证逻辑无关,可根据需求移除或改为生成输入密码的哈希用于显示对比。 - 增加异常处理:可以在数据库操作部分增加异常捕获,避免因数据库连接或查询错误导致程序崩溃。
内容的提问来源于stack exchange,提问作者Umberto Vizcaino
相关产品推荐
相关产品推荐

