You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

额外优化建议

  1. 移除或调整无关代码:原代码中password_hash = generate_password_hash("password", "sha256")是硬编码生成固定密码的哈希,和当前登录验证逻辑无关,可根据需求移除或改为生成输入密码的哈希用于显示对比。
  2. 增加异常处理:可以在数据库操作部分增加异常捕获,避免因数据库连接或查询错误导致程序崩溃。

内容的提问来源于stack exchange,提问作者Umberto Vizcaino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:15:42