修复后台弱密码提示误读本地配置问题
This commit is contained in:
@@ -54,18 +54,32 @@ def login():
|
||||
return jsonify({"success": False, "error": error}), 429
|
||||
return render_template('login.html', error=error)
|
||||
|
||||
# 优先使用数据库账号体系鉴权;若不可用则回退旧配置模式,保证兼容存量部署。
|
||||
# 优先使用数据库账号体系鉴权。
|
||||
#
|
||||
# 这里特意不再做“只要数据库校验失败就回退本地配置密码”的粗暴兜底,
|
||||
# 原因有两点:
|
||||
# 1. 一旦数据库里已经存在该管理员账号,真实口令状态应当以数据库为准;
|
||||
# 2. 如果继续无条件回退本地 config.toml,就会出现“数据库已改密,但本地默认密码仍然生效”
|
||||
# 的安全问题,也会让弱密码提示误判。
|
||||
#
|
||||
# 兼容策略调整为:
|
||||
# - 数据库可用且账号存在:只认数据库;
|
||||
# - 数据库不可用,或数据库里根本没有这个账号:才回退旧配置模式。
|
||||
login_ok = False
|
||||
db_account_exists = False
|
||||
if admin_db:
|
||||
try:
|
||||
login_ok = admin_db.verify_admin_password(username, password)
|
||||
db_account_exists = bool(admin_db.get_admin_by_username(username))
|
||||
if db_account_exists:
|
||||
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
|
||||
db_account_exists = False
|
||||
|
||||
if not login_ok:
|
||||
if not login_ok and not db_account_exists:
|
||||
login_ok = (username == server.username and password == server.password)
|
||||
|
||||
if login_ok:
|
||||
@@ -107,11 +121,18 @@ def logout():
|
||||
@login_required
|
||||
def get_security_status():
|
||||
"""返回当前登录管理员的安全状态。"""
|
||||
server = current_app.dashboard_server
|
||||
username = str(session.get("username", "") or "").strip()
|
||||
# 安全状态这里改成“实时重算 + 回写 session”,而不是只读登录瞬间写入的旧值:
|
||||
# 1. 避免管理员已经在数据库里改了密码,但当前会话仍保留旧的 force_password_change 标记;
|
||||
# 2. 避免本地配置和数据库状态不一致时,前端一直弹出错误的弱密码提示。
|
||||
force_password_change = bool(server.should_force_password_change(username)) if username else False
|
||||
session["force_password_change"] = force_password_change
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
"force_password_change": bool(session.get("force_password_change", False)),
|
||||
"session_timeout_minutes": int(current_app.dashboard_server.get_auth_policy().get("session_timeout_minutes", 480)),
|
||||
"force_password_change": force_password_change,
|
||||
"session_timeout_minutes": int(server.get_auth_policy().get("session_timeout_minutes", 480)),
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -307,16 +307,35 @@ class DashboardServer:
|
||||
def should_force_password_change(self, username: str) -> bool:
|
||||
"""判断当前管理员是否应该被强制提示修改密码。"""
|
||||
admin_db = getattr(self, "admin_account_db", None)
|
||||
if admin_db and admin_db.is_using_risky_password(username):
|
||||
return True
|
||||
normalized_username = str(username or "").strip()
|
||||
if not normalized_username:
|
||||
return False
|
||||
|
||||
# 判断弱密码时优先且尽量只相信数据库中的真实账号状态。
|
||||
#
|
||||
# 之前的问题在于:
|
||||
# 1. 代码先看数据库,再继续拿本地 config.toml 的默认用户名/密码做补充判断;
|
||||
# 2. 如果数据库中的管理员已经改成强密码,但本地配置仍保留 admin/admin123,
|
||||
# 前端仍会被误判成“当前账号在使用弱密码”;
|
||||
# 3. 这会让后台改密提示和真实账号状态脱节。
|
||||
#
|
||||
# 现在的策略改成:
|
||||
# - 数据库里存在该管理员账号:只按数据库口令哈希判断;
|
||||
# - 数据库里不存在该账号,才允许回退到旧配置模式,兼容尚未迁移完成的老部署。
|
||||
if admin_db:
|
||||
try:
|
||||
admin_row = admin_db.get_admin_by_username(normalized_username)
|
||||
if admin_row is not None:
|
||||
return admin_db.is_using_risky_password(normalized_username)
|
||||
except Exception as e:
|
||||
# 安全提示属于辅助能力,数据库偶发异常时不应因为误判把用户“锁”在改密弹窗里。
|
||||
# 因此这里记录 warning,并继续走兼容兜底,而不是直接强制提示弱密码。
|
||||
self.LOG.warning(f"读取后台账号安全状态失败,将尝试兼容兜底判断: username={normalized_username}, error={e}")
|
||||
|
||||
# 数据库体系不可用时,再回退配置值判断,至少把默认 admin/admin123 识别出来。
|
||||
fallback_username = str(self.username or "").strip()
|
||||
fallback_password = str(self.password or "").strip()
|
||||
return (
|
||||
str(username or "").strip() == fallback_username
|
||||
and fallback_password in getattr(admin_db, "RISKY_PASSWORDS", {"admin123", "admin"})
|
||||
)
|
||||
risky_passwords = getattr(admin_db, "RISKY_PASSWORDS", {"admin123", "admin"})
|
||||
return normalized_username == fallback_username and fallback_password in risky_passwords
|
||||
|
||||
def _register_blueprints(self, app):
|
||||
"""注册所有蓝图"""
|
||||
|
||||
Reference in New Issue
Block a user