PersonalWebApplication/docs/auth-login-gate.md
cc 7d2a1f0ea5 docs(auth): 同步去兜底——强制 DATABASE_URL + 补 wall_users 表
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 21:12:40 +08:00

4.7 KiB
Raw Permalink Blame History

登录 + 开发者入口门MySQL 后端)

两道关卡,都由后端 RustServer/src/auth.rs)实现,实时查 MySQL无兜底

  1. 入口门(藏门):起始页没有任何登录 UI 入口(设置齿轮已移除)。只有访问 http://<host>/#<hash><hash> 命中后端 dev_gate 表,前端才放行到登录页。
  2. 登录(身份):登录页提交用户名 + 密码,后端按 ccuser 表里的 SHA256 校验。

入口门只是「把门藏起来」的共享口令,不是身份凭证;真正鉴权是第 2 步的登录。

例外入口:地址栏 #photo 是写死的公开入口,不走入口门直接显示登录页(去掉顶部 负载栏),登录成功进照片墙。详见 photo-wall.md。第 2 步登录仍是同一套。

请求流

浏览器 #<hash>
  └─ POST /api/web/gate { hash }           → DevGate.allows()  查 dev_gate 表 → 命中才显示登录页
       登录页提交
  └─ POST /api/web/login { username, pwd }  → UserStore.verify() 查 ccuser 表 → 200 + token / 401
  • 前端:Client/src/api/gate.tscheckGate)、Client/src/App.tsx(监听 hashchange、防竞态、 回起始页时抹掉地址栏 hash、登录 Client/src/api/auth.ts
  • 后端:Server/src/auth.rs、路由 Server/src/routes/web.rs/api/web/gate/api/web/login

存储MySQL不缓存按需查库无兜底

机器内存紧张,所以不把整表读进内存UserStoreccuser)、WallUserStore wall_users,照片墙登录)、DevGatedev_gate)三者各持一个连接池,每次校验跑一条 索引查询。共用同一个 sqlx 懒连接池auth::db_pool_from_env()max 5 连接)。

  • 连接串来自环境变量 DATABASE_URL(线上写在 /opt/internet-project/weather.env mysql://KarCharon:<password>@127.0.0.1:3306/InternetProject
  • 强制要求 DATABASE_URL:未设置则 db_pool_from_env() 直接 panic,服务拒绝启动。 不再有任何写死账号 / 文件兜底(旧的内置写死表、GATE_FILE/dev_gate.txt 文件模式 已全部删除)——登录与入口门一律走数据库。本地开发也必须先把库搭好(见下)。
  • 依赖:sqlx 0.8features runtime-tokio, tls-rustls, mysql, macros

表结构(库 InternetProjectutf8mb4

CREATE TABLE ccuser (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(64) NOT NULL UNIQUE,
  password_sha256 CHAR(64) NOT NULL,         -- SHA256(明文) 的小写 hex
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE dev_gate (
  id INT AUTO_INCREMENT PRIMARY KEY,
  gate_hash VARCHAR(128) NOT NULL UNIQUE,     -- 与前端 URL `#` 后那串原样匹配
  label VARCHAR(64) DEFAULT NULL,             -- 备注(开发者名)
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE wall_users (                     -- 照片墙登录,与 ccuser 物理隔离
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(64) NOT NULL UNIQUE,
  password_sha256 CHAR(64) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
  • 加开发者用户:INSERT INTO ccuser (username, password_sha256) VALUES ('名', SHA2('明文',256));
  • 加照片墙用户:INSERT INTO wall_users (username, password_sha256) VALUES ('名', SHA2('明文',256));
  • 加开发者入口:INSERT INTO dev_gate (gate_hash, label) VALUES ('<hash>', '名'); (即时生效,无需重启。)
  • 当前 cc:登录密码 192118Lht;入口 hash 0086e83c9b10= 该密码 SHA256 的前 12 位)。 照片墙用户另有 UserTest(文件夹 607UserTest6340(文件夹 6340

一次性搭库(服务器本机 / 本地开发MySQL/MariaDB 仅监听 127.0.0.1

CREATE DATABASE InternetProject CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'KarCharon'@'localhost' IDENTIFIED BY '<password>';
GRANT ALL PRIVILEGES ON InternetProject.* TO 'KarCharon'@'localhost';
-- 然后建上面三张表ccuser / dev_gate / wall_users、插入初始数据。

因为已去兜底,本地开发同样要先搭库(无 DB 启动即 panic。MariaDB 即可,与 MySQL 兼容(SHA2()mysql_native_password 均支持)。启动后端时带上连接串: DATABASE_URL='mysql://KarCharon:<password>@127.0.0.1:3306/InternetProject' cargo run

安全注记(待办)

  • 密码是裸 SHA256无盐,仅保证「不落明文」,不抗暴力破解。对外网开放前应换 Argon2/bcrypt 这类慢哈希。
  • 登录返回的 token 目前没有任何接口校验,受保护路由实际尚未真正鉴权(见 issue_token 注释)。加鉴权中间件时再赋予其真实含义。