Flask 登录提交后返回 login.html 而不是 Login successful(MySQL)
提交表单后重新渲染登录页,直接原因是后端表单字段名校验和前端name属性不匹配,整个POST处理逻辑完全没执行。除此之外SQL列名、账号校验还有多个隐藏错误,按检查点逐一说明:
request.form 字段判断错误(核心触发原因)
前端输入框的name属性是下划线命名:login_username、login_password,但后端判断条件写成了驼峰命名loginUsername、loginPassword。键名不匹配导致POST内层判断直接不通过,最终走到最后一行重新渲染模板,和你遇到的现象完全吻合。
错误写法:if 'loginUsername' in request.form and 'loginPassword' in request.form:修正后:
if 'login_username' in request.form and 'login_password' in request.form:SQL 查询列名不规范(环境兼容bug)
注册接口的插入语句使用小写列名username、password,登录查询却写了首字母大写的Username、Password。MySQL在Linux默认配置下数据库标识符区分大小写,会直接报「未知列」错误。所有SQL里的列名必须和表结构完全一致,统一改为小写即可。
你目前用参数占位符传参的写法是正确的,可以避免SQL注入风险。账号密码校验逻辑错误
现有逻辑有两处硬伤,还有一处冗余:- 误用
is做值比较:Python中is用于判断两个变量是否指向同一块内存地址,判断字符串内容是否相等必须用==。从请求和数据库取出的同内容字符串通常不是同一个对象,用is判断必然会得到不相等的结果。 - 缺少空结果判断:如果账号或密码输入错误,
cursor.fetchone()会返回None,直接通过键取值会触发类型错误,导致页面500。 - 二次校验完全冗余:SQL的
WHERE条件已经完成了用户名+密码的匹配,只要查询结果不为空就代表校验通过,不需要再取出字段重复比对。
- 误用
仅修改核心bug、保留原有代码结构,修复后可正常完成登录校验:
@app.route('/login', methods=['POST', 'GET']) def login(): if request.method == 'POST': # 对齐前端表单字段名 if 'login_username' in request.form and 'login_password' in request.form: loginUsername = request.form['login_username'] loginPassword = request.form['login_password'] cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor) # 对齐表结构的小写列名 cursor.execute("SELECT * FROM logininfo WHERE username=%s AND password=%s", (loginUsername, loginPassword)) loginInfo = cursor.fetchone() cursor.close() # 查到结果即为校验通过 if loginInfo: return 'Login successful!' return 'Login unsuccessful' return render_template("login.html")
- 禁止明文存储密码:明文存密码属于严重安全漏洞,正式使用必须替换为哈希校验。
可直接使用Flask依赖自带的
werkzeug.security工具:注册时调用generate_password_hash(明文密码)生成密文存入数据库;登录时先按用户名查询用户记录,再调用check_password_hash(库中哈希值, 输入的明文密码)判断,不要在SQL语句中匹配密码。 - 记录登录状态:登录成功后需要把用户唯一标识(比如
userID)写入session,后续接口才能识别用户登录状态,仅返回成功字符串没有实际业务意义。 - 修复HTML语法错误:
login.html中密码行的标签有误,<p></p> Password: </p>是无效结构,修正为<p>Password:</p>即可。 - 统一资源释放:数据库游标用完主动调用
close()释放连接资源,和注册路由的写法保持一致。
内容的提问来源于stack exchange,提问作者Fat Trat

