安装向导:加管理员用户名,精简为填表即装、装完进首页 (#1 #2)

## 管理员账号(用户名 + 口令)
原先只有口令,没有用户名。现在两者都有:
- 用户名词入库 settings 的 admin.username(2~32 位,字母数字下划线点连字符)
- 口令仍是 bcrypt 哈希存 admin.password_hash,明文不落任何文件
- 登录校验 fb_admin_verify_login():用户名或口令任一不对都返回同一句
  「用户名或口令不正确」,且用户名错时也照常跑一次 password_verify,避免用耗时探测账号
- 向后兼容:老部署只设了口令没用户名时,仍可只填口令登录,
  并在登录页提示补一个用户名

## 安装向导精简
按用户要求「没数据就初始化,填完进主页」:
- 必填只剩 4 项:网站名称、管理员用户名、口令、确认口令
- 站点描述 / 官方邮箱 / 站点根地址改为 hidden(可留空自动探测)
- 密钥、令牌原本就自动生成
- 安装成功后展示网站名称与用户名,2 秒自动跳首页,也有按钮
- 按钮文案改为「完成安装,进入首页」

## 修掉一个真实 bug
首页把软件说明当成站点描述,导致「软件有 note 时站点描述被顶掉」。
两者是不同的东西:站点描述是全局设置必须始终显示,软件说明另起一行补充。
老基线 D6「首页描述变为新描述」就是被这个 bug 弄失败的。

## 另一个坑
admin.username 忘了加进 fb_setting_keys() 白名单,fb_set_setting() 会静默丢弃,
表现为「安装时填了用户名,装完却没有」。已补。

验证:
- 全新安装流程 32/32(真空站:无 config.php、无 data/*.db)
- 老基线 25/25、附件专项 22/22、安装向导 60/60
- PHP 8.5 全部入口 0 弃用
This commit is contained in:
2026-11-01 12:39:20 +08:00
parent 55d2dfa46b
commit 9b822d2d9a
4 changed files with 138 additions and 67 deletions
+25 -12
View File
@@ -25,21 +25,26 @@ if (isset($_GET['logout'])) {
/* ---------------- 登录 ---------------- */
$loginErr = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) {
$pw = isset($_POST['admin_password']) ? (string)$_POST['admin_password'] : '';
$cs = isset($_POST['csrf']) ? (string)$_POST['csrf'] : '';
$user = isset($_POST['admin_user']) ? (string)$_POST['admin_user'] : '';
$pw = isset($_POST['admin_password']) ? (string)$_POST['admin_password'] : '';
$cs = isset($_POST['csrf']) ? (string)$_POST['csrf'] : '';
if (!fb_csrf_ok($cs)) {
$loginErr = '会话已过期,请重试。';
} elseif (!fb_rate_check('admin_login', 10)) {
$loginErr = '尝试次数过多,请一小时后再试。';
} elseif (!fb_admin_password_is_set()) {
$loginErr = '本系统还没有设置登录口令,请先运行安装向导(install.php)完成设置。';
} elseif ($pw !== '' && fb_admin_verify_password($pw)) {
fb_admin_login();
fb_mod_log('login');
fb_redirect('admin.php');
} else {
fb_rate_hit('admin_login');
$loginErr = '口令不正确。';
$rc = fb_admin_verify_login($user, $pw);
if ($rc === 0) {
fb_admin_login();
fb_mod_log('login');
fb_redirect('admin.php');
} elseif ($rc === 2) {
$loginErr = '本系统还没有配置管理员账号,请先运行安装向导(install.php)完成设置。';
} else {
fb_rate_hit('admin_login');
// 不区分「用户名错」还是「口令错」,避免被用来探测账号
$loginErr = '用户名或口令不正确。';
}
}
}
@@ -49,13 +54,21 @@ if (!fb_admin_logged_in()) {
<div class="crumbs"><a href="index.php">← 返回问题列表</a></div>
<section class="narrow">
<h1>管理登录</h1>
<p class="muted">请输入管理员口令<?php if (fb_admin_password_source() === 'file'): ?>(当前仍是 <code>config.php</code> 里的 <code>admin_password</code> 明文,登录后请到「站点设置」改成加密存储)<?php endif; ?>。</p>
<p class="muted">请输入管理员用户名与口令<?php if (fb_admin_password_source() === 'file'): ?>(当前口令仍是 <code>config.php</code> 里的明文,登录后请到「站点设置」改成加密存储)<?php endif; ?>。</p>
<?php if (fb_admin_password_source() === 'none'): ?>
<div class="flash error">尚未设置登录口令,且出厂占位口令已被禁用。请运行 <a href="install.php">install.php</a> 设定一个。</div>
<div class="flash error">尚未配置管理员账号,且出厂占位口令已被禁用。请运行 <a href="install.php">install.php</a> 完成初始化。</div>
<?php endif; ?>
<?php if (fb_admin_username() === '' && fb_admin_password_is_set()): ?>
<div class="flash error">本站只设了口令、没有用户名(旧版安装)。请运行 <a href="install.php">install.php</a> 补一个用户名;在那之前用户名可留空、只填口令。</div>
<?php endif; ?>
<?php fb_flash_box($loginErr, 'error'); ?>
<form method="post" action="admin.php" class="card-form">
<input type="hidden" name="csrf" value="<?php echo e(fb_csrf_token()); ?>">
<label class="field">
<span>管理员用户名</span>
<input type="text" name="admin_user" autocomplete="username" required
value="<?php echo e(isset($_POST['admin_user']) ? (string)$_POST['admin_user'] : ''); ?>">
</label>
<label class="field">
<span>管理员口令</span>
<input type="password" name="admin_password" autocomplete="current-password" required>