一、锁定机制(为什么会进不去)
XIUNOX 后台登录有双重维度防暴破锁定(LoginSecurityService.php):
1. uid 维度(针对管理员账号本身)
bbs_user表的login_attempts字段累计失败次数达到 3 次时写入
banned_until = 当前时间 + 900锁定期内
checkBan()拦截登录,返回login_banned提示
2. IP 维度(针对攻击 IP)
基于
bbs_user_login_log表统计该 IP 在 900 秒窗口内失败次数达到 3 次即锁,锁定期 = 第 3 次失败时间 + 900 秒
防止用不存在的用户名枚举绕过 uid 限流
关键:登录入口 admin/route/index.php 会先调用 checkIpBan($longip) 再调用 checkBan($uid),两道关卡任一拦截都无法登录。
二、解锁方案
方案 A:等待自动解锁(推荐,最安全)
uid 维度:15 分钟后
banned_until到期,下次登录时checkBan()自动重置login_attempts=0, banned_until=0IP 维度:900 秒窗口外的失败记录失效后自动恢复
适合不紧急的情况
方案 B:数据库直接重置(立即解锁,需有 DB 权限)
步骤 1:查看锁定状态
SELECT uid, username, login_attempts, banned_until,
FROM_UNIXTIME(banned_until, '%Y-%m-%d %H:%i:%s') AS unlock_at,
ban_type,
CASE
WHEN ban_type > 0 THEN '被UserBanService封禁(非登录锁定)'
WHEN banned_until > UNIX_TIMESTAMP() THEN CONCAT('登录锁定中,剩余', banned_until - UNIX_TIMESTAMP(), '秒')
ELSE '正常'
END AS status
FROM bbs_user
WHERE username='你的管理员用户名';步骤 2:重置 uid 维度锁定
-- 关键:同时重置 login_attempts 和 banned_until,不要动 ban_type
UPDATE bbs_user
SET login_attempts=0, banned_until=0
WHERE uid=管理员UID;步骤 3:清理 IP 维度失败记录(如 IP 也被锁)
-- 查看最近失败记录(ip 字段是 ip2long 整型,不是点分十进制)
SELECT ip, time, success FROM bbs_user_login_log
WHERE success=0 ORDER BY time DESC LIMIT 20;
-- 清理该 IP 的失败记录(替换为实际 longip 值)
DELETE FROM bbs_user_login_log WHERE ip=你的IP的longip值 AND success=0;步骤 4:重新登录后台
访问 /admin 重新登录。
三、注意事项(重要,避免踩坑)
不要修改
ban_type字段:ban_type属于UserBanService封禁系统(禁言/禁止访问/锁定),与登录失败锁定无关。ban_type>0时反而会跳过登录锁定检查。
必须同时重置
login_attempts和banned_until:只重置banned_until不重置login_attempts,下次失败一次就会立刻再次触发锁定(因为计数仍在)。
banned_until字段被两系统复用:LoginSecurityService 写登录失败锁定,UserBanService::ban 写封禁到期。靠ban_type区分来源(见 LoginSecurityService.php:13-16 注释)。
IP 维度的
ip字段是整型:用 PHPip2long('1.2.3.4')转换,或直接看现有记录的值。
清缓存无关:登录锁定状态读自
user表,不走缓存,重置后立即生效,无需清tmp/cache/。
四、调整锁定阈值(可选)
觉得 3 次太严格,可在 conf/conf.php 修改:
'login_max_attempts' => 5, // 允许失败次数
'login_ban_duration' => 900, // 锁定时长(秒)或在后台「设置 → 安全设置」调整(由 SecurityConfigService 同步写入)。
