后台账号体系改造:接入t_admin_数据库账号与前端改密
变更项: 1. 新增 db/admin_account_db.py,提供 t_admin_accounts 表初始化、PBKDF2口令哈希、登录校验、登录信息回写与密码更新能力。 2. DashboardServer 启动时接入账号数据层,自动建表并把旧配置默认账号迁移为数据库账号种子。 3. 重构 auth 登录逻辑:优先走数据库账号鉴权,保留旧配置账号回退;新增 /api/auth/change_password 接口支持在线修改密码。 4. base.html 增加顶部修改密码入口与弹窗表单,前端可直接提交旧密码与新密码完成改密。 5. login.html 增强小屏适配:允许纵向滚动、768以下隐藏展示侧栏并优化输入区间距与字号,修复移动端登录体验。 6. 新增迁移脚本 db/scripts/migrations/20260423_add_admin_account_table.sql,便于独立数据库升级。
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, session, current_app
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, session, current_app, jsonify
|
||||
from functools import wraps
|
||||
from loguru import logger
|
||||
|
||||
@@ -22,13 +22,29 @@ def login_required(f):
|
||||
def login():
|
||||
error = None
|
||||
if request.method == 'POST':
|
||||
username = request.form['username']
|
||||
password = request.form['password']
|
||||
# 使用 strip 规避用户误输入首尾空格导致的误判。
|
||||
username = str(request.form.get('username', '') or '').strip()
|
||||
password = str(request.form.get('password', '') or '')
|
||||
|
||||
# 从应用上下文获取服务器实例,而不是从蓝图对象
|
||||
server = current_app.dashboard_server
|
||||
admin_db = getattr(server, "admin_account_db", None)
|
||||
|
||||
if username == server.username and password == server.password:
|
||||
# 优先使用数据库账号体系鉴权;若不可用则回退旧配置模式,保证兼容存量部署。
|
||||
login_ok = False
|
||||
if admin_db:
|
||||
try:
|
||||
login_ok = admin_db.verify_admin_password(username, password)
|
||||
if login_ok:
|
||||
admin_db.mark_login_success(username, request.remote_addr or "")
|
||||
except Exception as e:
|
||||
logger.error(f"数据库账号登录校验异常,回退配置模式: {e}")
|
||||
login_ok = False
|
||||
|
||||
if not login_ok:
|
||||
login_ok = (username == server.username and password == server.password)
|
||||
|
||||
if login_ok:
|
||||
session['logged_in'] = True
|
||||
session['username'] = username # 存储用户名到session
|
||||
logger.debug(f"Login successful. Session after login: {dict(session)}")
|
||||
@@ -45,3 +61,56 @@ def logout():
|
||||
session.pop('logged_in', None)
|
||||
session.pop('username', None) # 同时删除username
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
|
||||
@auth_bp.route('/api/auth/change_password', methods=['POST'])
|
||||
@login_required
|
||||
def change_password():
|
||||
"""修改当前登录管理员密码。
|
||||
|
||||
前端请求参数:
|
||||
{
|
||||
"old_password": "旧密码",
|
||||
"new_password": "新密码",
|
||||
"confirm_password": "确认新密码"
|
||||
}
|
||||
"""
|
||||
server = current_app.dashboard_server
|
||||
admin_db = getattr(server, "admin_account_db", None)
|
||||
if not admin_db:
|
||||
return jsonify({"success": False, "error": "账号数据库未初始化,无法修改密码"}), 500
|
||||
|
||||
payload = request.get_json(silent=True) or {}
|
||||
old_password = str(payload.get("old_password", "") or "")
|
||||
new_password = str(payload.get("new_password", "") or "")
|
||||
confirm_password = str(payload.get("confirm_password", "") or "")
|
||||
username = str(session.get("username", "") or "").strip()
|
||||
|
||||
if not username:
|
||||
return jsonify({"success": False, "error": "会话失效,请重新登录"}), 401
|
||||
|
||||
if not old_password or not new_password or not confirm_password:
|
||||
return jsonify({"success": False, "error": "请完整填写旧密码与新密码"}), 400
|
||||
|
||||
if new_password != confirm_password:
|
||||
return jsonify({"success": False, "error": "两次输入的新密码不一致"}), 400
|
||||
|
||||
# 密码长度做基础约束,避免过弱口令。
|
||||
if len(new_password) < 6:
|
||||
return jsonify({"success": False, "error": "新密码长度不能少于6位"}), 400
|
||||
|
||||
if new_password == old_password:
|
||||
return jsonify({"success": False, "error": "新密码不能与旧密码相同"}), 400
|
||||
|
||||
try:
|
||||
if not admin_db.verify_admin_password(username, old_password):
|
||||
return jsonify({"success": False, "error": "旧密码错误"}), 400
|
||||
|
||||
updated = admin_db.update_password(username, new_password)
|
||||
if not updated:
|
||||
return jsonify({"success": False, "error": "密码更新失败,请稍后重试"}), 500
|
||||
|
||||
return jsonify({"success": True, "message": "密码修改成功"})
|
||||
except Exception as e:
|
||||
logger.error(f"修改后台密码失败: username={username}, error={e}")
|
||||
return jsonify({"success": False, "error": "密码修改失败,请检查日志"}), 500
|
||||
|
||||
Reference in New Issue
Block a user