账号数据 - lmxdg/ZeroLogin GitHub Wiki
ZeroLogin v1.1.0 提供两种账号存储后端,由 storage.type 决定:
| 后端 | 位置 | 适用场景 |
|---|---|---|
sqlite(默认) |
plugins/ZeroLogin/zerologin.db |
一般服务器、账号较多 |
file(v1.0 后端) |
plugins/ZeroLogin/accounts/<UUID>.txt |
少量账号、共享目录多服部署 |
单文件数据库 plugins/ZeroLogin/zerologin.db,WAL 日志模式。所有 SQL 在专用 IO 线程上串行执行,不阻塞服务端主线程。
CREATE TABLE accounts (
uuid TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
name_lc TEXT NOT NULL, -- 小写玩家名,用于大小写不敏感查询
password TEXT NOT NULL, -- $pbkdf2$<迭代>$<盐>$<散列>
registered_at INTEGER NOT NULL DEFAULT 0,
last_login_at INTEGER NOT NULL DEFAULT 0,
last_seen_at INTEGER NOT NULL DEFAULT 0,
login_count INTEGER NOT NULL DEFAULT 0,
auto_login_ips TEXT NOT NULL DEFAULT '' -- 逗号分隔
);
CREATE UNIQUE INDEX idx_accounts_name_lc ON accounts(name_lc);-
uuid主键:玩家改名只更新name/name_lc,不丢数据 -
name_lc唯一索引:按名字查询大小写不敏感,改名后按新名字仍可命中 -
单行更新:写账号使用
INSERT ... ON CONFLICT(uuid) DO UPDATE,只改该玩家一行 -
批量迁移单事务:迁移与导入走
saveAll,一次提交,失败整体回滚 -
完整性自检:启动时执行
PRAGMA integrity_check,异常只告警不阻断启用 -
驱动内联:
sqlite-jdbc打包时 relocate 到dev.zerologin.libs.sqlite,不依赖服务端环境
停止服务端后复制一个文件即可(若存在 -wal / -shm 侧文件,一并复制或先跑一次 checkpoint):
# 停止服务端后
cp plugins/ZeroLogin/zerologin* /backup/plugins/ZeroLogin/accounts/ 目录下每个账号一个文件,文件名即玩家 UUID,格式为可读的 key value 纯文本:
# ZeroLogin account record. Edit at your own risk.
schema 1
uuid 069a79f4-44e9-4726-a5be-fca90e38aaf5
name Steve
password $pbkdf2$120000$<盐(Base64)>$<散列(Base64)>
registered-at 1696000000000
last-login-at 1696000100000
last-seen-at 1696000100000
login-count 3
auto-login-ips 1.2.3.4,fe80::1
| 字段 | 说明 |
|---|---|
schema |
数据格式版本 |
uuid |
玩家 UUID(离线模式为按名字生成的离线 UUID) |
name |
最后观察到的玩家名,用于按名字查询 |
password |
PBKDF2 散列,格式见下表 |
registered-at |
注册时间(毫秒时间戳) |
last-login-at |
最近登录时间 |
last-seen-at |
最近在线时间 |
login-count |
累计登录次数 |
auto-login-ips |
自动登录 IP(逗号分隔,最多 5 个) |
- 文件名为 UUID:玩家改名(含正版改名)不会造成主键冲突或数据丢失
- 单账号单文件写入:登录高峰只重写对应玩家的小文件,不会整库重写
-
原子写入:先写
.tmp再原子替换,避免服务端崩溃导致文件损坏 - 损坏容错:无法解析的文件会被安全跳过并记录警告,不会导致插件启动失败
$pbkdf2$<迭代次数>$<盐(Base64)>$<散列(Base64)>
- 算法:PBKDF2-HMAC-SHA256
- 盐:随机 16 字节
- 散列长度:256 位
首次以 SQLite 启动且数据库为空时,插件自动导入 accounts/ 下的账号(非破坏式,原文件保留)。可用 storage.sqlite.import-file: false 关闭。
/zerologin migrate <from> <to> [force]
| 情形 | 行为 |
|---|---|
| 目标后端为空 | 直接导入 |
| 目标后端已有账号 |
中止并提示数量,需显式加 force
|
加了 force
|
先把目标后端现有账号导出为文本备份到 backups/migrate-<时间戳>/,再导入 |
| 同名但 UUID 不同 | 跳过该账号并汇报跳过数量 |
| 源后端为空 | 提示无可迁移数据 |
切换后端流程:停止服务端 →
/zerologin migrate <当前后端> <目标后端>→ 修改storage.type→ 启动服务端。
-
sqlite 后端:停止两端服务端,把
zerologin.db(连同-wal/-shm侧文件)复制到新服相同位置即可 -
file 后端:把旧服的
plugins/ZeroLogin/accounts/复制到新服相同位置
离线模式下 UUID 由玩家名生成,只要玩家名不变,账号即可在新服继续使用。
-
file 后端:可将多台服务端的
accounts/指向共享存储(NFS / SMB / 定期同步)。并发写入同一账号文件可能冲突,建议各服错峰。 - sqlite 后端:单文件数据库适合「整库复制」,不适合多服并发读写同一文件。多服实时共享待后续 MySQL 后端。
⚠️ 不建议手工编辑账号数据。写入格式非法会导致该账号无法读取(file 后端会被安全跳过,SQLite 则可能破坏表约束)。
常见用途:
| 需求 | sqlite 后端 | file 后端 |
|---|---|---|
| 玩家忘记密码 | DELETE FROM accounts WHERE name_lc = '<名字小写>' |
删除该玩家的 .txt
|
| 清空某玩家 IP 白名单 | 把该行 auto_login_ips 置为 ''
|
删除文件中 auto-login-ips 行 |
| 手动迁移某个账号 |
SELECT * FROM accounts 导出后插入 |
复制对应 .txt 文件 |
手工操作数据库前请先停止服务端或做好备份。