身份认证
首次初始化
Server 首次启动时不建任何管理员。打开面板,第一个访问的人设定自己的 用户名和密码。
这里有一个窗口,说清楚
在你完成设置之前,任何能打开这个地址的人都可以抢先创建管理员。
这是为了换取「装完点开就能用,不必去日志里翻一次性密码」而付出的代价。 Pulse 选择把它明说,而不是假装不存在。
已经做了的收敛:
| 判空与写入是同一条 SQL | 不存在两个人都建成的情况(WHERE NOT EXISTS),有并发测试盯着 |
| 建成之后接口永久失效 | 再调返回 409,不是「改密码」入口 |
| 抢注会被记录 | 以 warn 级别记下 IP 和用户名,事后能查 |
| 限流保护 argon2 | 「已初始化」和参数校验都在限流之前返回,不消耗额度 |
不能接受这个窗口的话
无人值守部署(Docker、批量)可以在启动时给 PULSE_ADMIN_PASSWORD (可配 PULSE_ADMIN_USERNAME,默认 admin), Server 会先把管理员建好, 初始化接口从一开始就是 409。
bash
PULSE_ADMIN_PASSWORD='至少八位' ./pulse-server装完请立刻设置
安装脚本执行完会打印Server 地址并提示这一点。别装完就去忙别的。
凭据怎么存
| Agent token | 数据库里只存 SHA-256,明文只在生成时返回一次 |
| 管理员密码 | Argon2id 哈希 |
| 通知渠道密钥 | 加密存储,接口返回时打码 |
因为库里取不回明文,「重新生成安装命令」只能换一把新 token。 已经装了 Agent 的机器会掉线,直到用新命令重装 —— 后台点之前会提醒。
会话
- access token 只在内存里,刷新页面就没了
- refresh token 放在
HttpOnly+SameSite=Strict的 cookie 里, 路径限定在/api/v1/auth, JS 拿不到, XSS 也偷不走 - Server 走 HTTPS 时 cookie 自动带
Secure - 退出登录会把仍在有效期内的 refresh token 拉黑
登录保护
- 按来源 IP 限流: 60 秒内最多 5 次
- 连续失败 10 次锁定一段时间
- 限流在验密码之前执行 —— 否则 argon2 就成了 DoS 放大器
- 用户不存在时也走一次同样耗时的哈希校验, 这样响应时间不会泄露「这个用户名存不存在」
- 登录失败不区分「用户不存在」和「密码错误」
服务端密钥
PULSE_SECRET_KEY 用于加密通知渠道的凭据。不设的话会在 PULSE_DATA_DIR/secret.key 自动生成。
单独备份它
这个密钥丢了,所有通知渠道的凭据都解不开。 备份数据库时记得一起备份它。
反向代理
放在反代后面时要设 PULSE_TRUSTED_PROXY_HOPS 为代理层数, 否则 Server 会忽略 X-Forwarded-For(直连部署的正确默认值), 限流和日志里看到的就都是代理的 IP。