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

基于Python&MySQL的用户数据库:密码加盐哈希存储及Flask适配问题

Flask + MySQL 安全密码存储与验证方案

一、数据库表设计优化

先明确两个核心方案的表结构:

方案1:用Bcrypt(推荐,自动管理盐值)

Bcrypt会自动把盐值嵌入哈希结果,无需单独存储盐字段,表结构更简洁:

CREATE TABLE user_passwords (
    user_id INT PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);

方案2:自定义盐+SHA256(手动存储盐值)

如果坚持单独存盐,表结构如下:

CREATE TABLE user_passwords (
    user_id INT PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    salt VARCHAR(255) NOT NULL,
    password_hash VARCHAR(64) NOT NULL, -- SHA256哈希固定64位十六进制
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);

二、Flask代码实现(适配request.form)

1. Bcrypt方案(最安全且易维护)

先安装依赖:

pip install flask-bcrypt

Flask应用核心代码:

from flask import Flask, request
from flask_bcrypt import Bcrypt
import mysql.connector

app = Flask(__name__)
bcrypt = Bcrypt(app)

# 配置MySQL连接(替换为你的实际参数)
db = mysql.connector.connect(
    host="localhost",
    user="your_db_user",
    password="your_db_pwd",
    database="your_db_name"
)
cursor = db.cursor()

# 注册接口:处理表单数据并存储
@app.route('/register', methods=['POST'])
def register():
    # 从request.form获取所有字段
    user_id = request.form.get('user_id')
    first_name = request.form.get('first_name')
    last_name = request.form.get('last_name')
    email = request.form.get('email')
    dob = request.form.get('dob')
    password = request.form.get('password')

    # 1. 插入基础用户信息到users表
    insert_user_sql = """
        INSERT INTO users (user_id, first_name, last_name, email, dob)
        VALUES (%s, %s, %s, %s, %s)
    """
    cursor.execute(insert_user_sql, (user_id, first_name, last_name, email, dob))

    # 2. 生成Bcrypt哈希(自动包含盐值,转字符串存库)
    pw_hash = bcrypt.generate_password_hash(password).decode('utf-8')

    # 3. 插入哈希到密码表
    insert_pw_sql = """
        INSERT INTO user_passwords (user_id, email, password_hash)
        VALUES (%s, %s, %s)
    """
    cursor.execute(insert_pw_sql, (user_id, email, pw_hash))

    db.commit()
    return "注册成功"

# 登录接口:验证密码
@app.route('/login', methods=['POST'])
def login():
    email = request.form.get('email')
    password = request.form.get('password')

    # 从库中取出存储的哈希
    cursor.execute("SELECT password_hash FROM user_passwords WHERE email = %s", (email,))
    result = cursor.fetchone()

    if result:
        stored_hash = result[0]
        # 验证密码匹配
        if bcrypt.check_password_hash(stored_hash, password):
            return "登录成功"
        return "密码错误"
    return "用户不存在"

2. 自定义盐+SHA256方案

如果必须手动管理盐值,用secrets生成安全随机盐:

import secrets
import hashlib

# 注册接口
@app.route('/register', methods=['POST'])
def register():
    # 其他字段获取同上
    password = request.form.get('password')

    # 生成16字节随机盐(转32位十六进制字符串)
    salt = secrets.token_hex(16)
    # 加盐后哈希
    salted_pw = password + salt
    pw_hash = hashlib.sha256(salted_pw.encode('utf-8')).hexdigest()

    # 插入盐和哈希到库
    insert_pw_sql = """
        INSERT INTO user_passwords (user_id, email, salt, password_hash)
        VALUES (%s, %s, %s, %s)
    """
    cursor.execute(insert_pw_sql, (user_id, email, salt, pw_hash))
    db.commit()
    return "注册成功"

# 登录验证
@app.route('/login', methods=['POST'])
def login():
    email = request.form.get('email')
    password = request.form.get('password')

    cursor.execute("SELECT salt, password_hash FROM user_passwords WHERE email = %s", (email,))
    result = cursor.fetchone()

    if result:
        salt, stored_hash = result
        # 用相同盐生成哈希对比
        computed_hash = hashlib.sha256((password + salt).encode('utf-8')).hexdigest()
        if computed_hash == stored_hash:
            return "登录成功"
        return "密码错误"
    return "用户不存在"

三、你之前适配失败的常见原因

  • 前端表单密码输入框的name属性不是password:确保是<input type="password" name="password">,否则request.form.get('password')会返回None
  • 哈希结果未转字符串:Bcrypt生成的是字节串,必须用decode('utf-8')转成字符串才能存入MySQL
  • 数据库字段长度不足:Bcrypt哈希约60位,需设VARCHAR(255);SHA256哈希是64位,设VARCHAR(64)即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:07:08