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

89 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 登录 + 开发者入口门MySQL 后端)
两道关卡,都由后端 Rust`Server/src/auth.rs`)实现,**实时查 MySQL无兜底**
1. **入口门(藏门)**:起始页没有任何登录 UI 入口(设置齿轮已移除)。只有访问
`http://<host>/#<hash>``<hash>` 命中后端 `dev_gate` 表,前端才放行到登录页。
2. **登录(身份)**:登录页提交用户名 + 密码,后端按 `ccuser` 表里的 SHA256 校验。
> 入口门只是「把门藏起来」的共享口令,**不是身份凭证**;真正鉴权是第 2 步的登录。
> 例外入口:地址栏 `#photo` 是写死的公开入口,**不走入口门**直接显示登录页(去掉顶部
> 负载栏),登录成功进照片墙。详见 [photo-wall.md](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.ts``checkGate`)、`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不缓存按需查库**无兜底**
机器内存紧张,所以**不把整表读进内存**`UserStore``ccuser`)、`WallUserStore`
`wall_users`,照片墙登录)、`DevGate``dev_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.8`features `runtime-tokio, tls-rustls, mysql, macros`
### 表结构(库 `InternetProject`utf8mb4
```sql
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`(文件夹 607、`UserTest6340`(文件夹 6340
## 一次性搭库(服务器本机 / 本地开发MySQL/MariaDB 仅监听 127.0.0.1
```sql
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` 注释)。加鉴权中间件时再赋予其真实含义。