fix(auth): 修复登录后反复报未配置账号并跳回登录页的死循环
根因:ny_save_config 只写不校验,Db::settingsSet 内部吞异常且返回 void。 data/ 目录不可写时登录页照常显示登录成功,但下一请求读到的账号仍是空的 → 抛未配置卷王登录账号 → 前端 auth 打标 → 跳登录页 → 无限循环。 修复: - Db::settingsSet 改返回 bool 并回读校验;新增 settingsDelete - ny_save_config 双写后均做回读校验,失败写入 ny_config_save_error() - 新增 ny_config_diag()/ny_session_usable(),暴露来源/可写性/是否已存账号 - ny_load_config 把 null 账号强制成空字符串(脏数据不再伪装成未配置) - login.php 存凭据后回读确认,存不住/会话不可写直接报错而不是假成功 - login.php 账号为空时页面直接给出 data 目录写权限提示 - config_save 合并逻辑抽成 ny_apply_config_input:账号/密码不许被改空 - 鉴权失败响应带 extra.diag,前端 401 也算 auth - 前端防死循环:刚登录 120s 内或已跳 2 次则停止自动跳转,弹窗给出真实原因+诊断 测试:新增 tests/test-config-persist.php(29) 与 tools/test-login-loop.js(19); run-all.sh 纳入两者。全套 148+48=196 项通过。
This commit is contained in:
@@ -171,66 +171,10 @@ try {
|
||||
$in = $_POST;
|
||||
}
|
||||
$old = cfg();
|
||||
$allowed = ['base_url', 'api_prefix', 'username', 'timeout', 'refresh_interval', 'page_size', 'name_keywords', 'history_display', 'export_sort'];
|
||||
$new = $old;
|
||||
foreach ($allowed as $k) {
|
||||
if (array_key_exists($k, $in)) {
|
||||
$new[$k] = is_string($in[$k]) ? trim((string)$in[$k]) : $in[$k];
|
||||
}
|
||||
}
|
||||
// 密码:保留首尾空格的原貌,空 / 占位符 = 不修改
|
||||
if (array_key_exists('password', $in)) {
|
||||
$pwdIn = (string)$in['password'];
|
||||
if ($pwdIn !== '' && $pwdIn !== '******') {
|
||||
$new['password'] = $pwdIn;
|
||||
}
|
||||
}
|
||||
foreach (['verify_ssl', 'include_temp_save', 'dedupe'] as $k) {
|
||||
if (array_key_exists($k, $in)) {
|
||||
$new[$k] = filter_var($in[$k], FILTER_VALIDATE_BOOL);
|
||||
}
|
||||
}
|
||||
// 布局配置
|
||||
if (array_key_exists('layout', $in)) {
|
||||
$new['layout'] = ($in['layout'] === 'side') ? 'side' : 'default';
|
||||
}
|
||||
// 历史成绩展示方式:click(点击成员弹窗,默认) / inline(明细内全部展开)
|
||||
if (array_key_exists('history_display', $in)) {
|
||||
$new['history_display'] = ($in['history_display'] === 'inline') ? 'inline' : 'click';
|
||||
}
|
||||
// 成绩导出排序:time(按提交时间降序,默认)/ sid(按学号)/ score_desc(成绩降序)/ score_asc(成绩升序)
|
||||
if (array_key_exists('export_sort', $in)) {
|
||||
$v = (string)$in['export_sort'];
|
||||
$new['export_sort'] = in_array($v, ['time','sid','score_desc','score_asc'], true) ? $v : 'time';
|
||||
}
|
||||
// 说明:「各试卷独立满分」已移出设置,改为在主页面针对当前试卷配置
|
||||
// (project_config / project_config_save),设置里只保留「全局默认满分」。
|
||||
if (array_key_exists('pass_rate', $in)) {
|
||||
$pr = (float)$in['pass_rate'];
|
||||
$new['pass_rate'] = ($pr >= 1 && $pr <= 100) ? $pr : 60;
|
||||
}
|
||||
$new['base_url'] = rtrim((string)$new['base_url'], '/');
|
||||
$new['api_prefix'] = '/' . trim((string)$new['api_prefix'], '/');
|
||||
$new['timeout'] = (int)$new['timeout'];
|
||||
$new['refresh_interval'] = (int)$new['refresh_interval'];
|
||||
if ($new['refresh_interval'] < 3) {
|
||||
$new['refresh_interval'] = 3;
|
||||
}
|
||||
// 默认满分
|
||||
$fs = (int)($in['full_score'] ?? $new['full_score'] ?? 100);
|
||||
if ($fs < 1) {
|
||||
$fs = 100;
|
||||
}
|
||||
$new['full_score'] = $fs;
|
||||
// 仅当连接信息真的变了才清 token + 重连;保存满分/布局等不应触发登录卷王
|
||||
$connKeys = ['base_url', 'api_prefix', 'username', 'password', 'verify_ssl'];
|
||||
$connChanged = false;
|
||||
foreach ($connKeys as $k) {
|
||||
if ((string)($old[$k] ?? '') !== (string)($new[$k] ?? '')) {
|
||||
$connChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 合并规则统一放在 ny_apply_config_input(含"账号/密码不许被改空"的兜底),便于单测
|
||||
$applied = ny_apply_config_input($old, $in);
|
||||
$new = $applied['config'];
|
||||
$connChanged = $applied['conn_changed'];
|
||||
ny_save_config($new);
|
||||
if ($connChanged) {
|
||||
@unlink(NY_DATA . '/cache/token.json');
|
||||
@@ -954,8 +898,11 @@ try {
|
||||
$isAuth = str_contains($msg, '未配置卷王登录账号')
|
||||
|| str_contains($msg, '登录卷王失败')
|
||||
|| str_contains($msg, '登录失败');
|
||||
// 鉴权失败时回传落盘诊断(账号到底有没有存住、data 目录可不可写),
|
||||
// 否则前端只能给出"账号未配置"这一句空话,用户无法自查,也容易陷入反复跳登录页。
|
||||
ny_fail($msg, [
|
||||
'auth' => $isAuth,
|
||||
'diag' => $isAuth ? ny_config_diag() : null,
|
||||
'trace' => defined('NY_DEBUG') && NY_DEBUG ? $e->getTraceAsString() : null,
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user