Flask中如何实现数据库密码更新并支持新密码登录?
Flask密码更新功能修复方案
核心问题梳理
- 表单类误用:你创建了UpdateForm但路由里用的是LoginForm,导致自定义表单规则完全没生效。
- 数据库更新逻辑错误:POST请求里直接把
update_password(数据库查询到的User对象)覆盖成了表单密码字符串,根本没修改用户实例的密码字段;而且直接存明文密码,登录时哈希校验肯定不通过。 - 事务处理混乱:重复调用
db.session.commit(),且异常捕获范围没包裹关键的修改操作,出错也无法正确回滚。 - 页面表单缺失:update.html里没有提交按钮,用户没法触发POST请求;也没加CSRF令牌,可能导致请求被拦截。
修正后的路由代码
from flask import flash, redirect, render_template, request, url_for from werkzeug.security import generate_password_hash # 请替换成你实际的模块导入路径 from your_app import UpdateForm, User, db, login_required @app.route('/updatepass/<int:id>', methods=['GET', 'POST']) @login_required def updatepass(id): form = UpdateForm() # 改用自定义的UpdateForm user = User.query.get_or_404(id) # 用get_or_404避免找不到用户的异常 # 用WTForms自带的validate_on_submit处理表单验证和POST判断 if form.validate_on_submit(): # 对新密码做哈希处理,绝对不能存明文 user.password = generate_password_hash(form.password.data) try: db.session.commit() flash("密码更新成功!") return redirect(url_for('login')) # 重定向到登录页更合理 except Exception as e: db.session.rollback() # 出错时回滚事务 flash(f"更新失败:{str(e)}") return redirect(url_for('updatepass', id=id)) # GET请求时清空密码输入框,让用户输入新密码(不要显示旧密码) form.password.data = "" return render_template("update.html", form=form, user=user)
修正后的update.html代码
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>修改密码</title> </head> <body> <h1>修改密码</h1> <form method="POST"> {{ form.hidden_tag() }} <!-- 必须添加CSRF令牌,防止跨站请求伪造 --> <div> {{ form.password.label }} {{ form.password(class="form-control", placeholder="请输入新密码") }} <!-- 显示表单验证错误提示 --> {% for error in form.password.errors %} <span style="color:red">{{ error }}</span> {% endfor %} </div> <button type="submit">确认修改</button> <!-- 添加提交按钮,触发POST请求 --> </form> <!-- 显示flash提示消息 --> {% with messages = get_flashed_messages() %} {% if messages %} {% for msg in messages %} <p>{{ msg }}</p> {% endfor %} {% endif %} {% endwith %} </body> </html>
额外必要配置
- 正确定义UpdateForm:确保你的表单类包含密码验证规则,示例如下:
from flask_wtf import FlaskForm from wtforms import PasswordField from wtforms.validators import DataRequired, Length class UpdateForm(FlaskForm): password = PasswordField('新密码', validators=[DataRequired(), Length(min=6)])
- 登录校验一致性:登录时必须用
check_password_hash(user.password, input_password)来验证密码,保证和更新时的哈希逻辑一致。 - 权限校验:添加登录用户权限判断,防止越权修改他人密码:
from flask_login import current_user from flask import abort # 在路由开头添加 if current_user.id != id: abort(403) # 返回403禁止访问
内容的提问来源于stack exchange,提问作者fasterjake
相关产品推荐
相关产品推荐

