PersonalWebApplication/docs/auth-login-gate.md
cc d240c128dc feat(photo-wall): client-only photo wall behind #photo login entry
已部署到线上(frontend-only)。本提交把工作区里已上线但未提交的实现固化为分支基线。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 20:55:03 +08:00

76 lines
3.8 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` 与 `DevGate` 都是
`Db(pool) | Memory(兜底)` 两态DB 模式下每次校验跑一条索引查询。
二者**共用同一个 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`** → 各自回退:用户用内置写死表(仅 `cc`)、入口门读 `GATE_FILE`
(默认 `dev_gate.txt`)再退内置。方便本地无 DB 时开发。
- 依赖:`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
);
```
- 加用户:`INSERT INTO ccuser (username, password_sha256) VALUES ('名', SHA2('明文',256));`
- 加开发者入口:`INSERT INTO dev_gate (gate_hash, label) VALUES ('<hash>', '名');`
DB 模式即时生效,无需重启。)
- 当前 `cc`:登录密码 `192118Lht`;入口 hash `0086e83c9b10`= 该密码 SHA256 的前 12 位)。
## 一次性搭库服务器本机MySQL 仅监听 127.0.0.1
```sql
CREATE DATABASE InternetProject CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'KarCharon'@'localhost' IDENTIFIED WITH mysql_native_password BY '<password>';
GRANT ALL PRIVILEGES ON InternetProject.* TO 'KarCharon'@'localhost';
-- 然后建上面两张表、插入初始数据。
```
## 安全注记(待办)
- 密码是**裸 SHA256无盐**,仅保证「不落明文」,不抗暴力破解。对外网开放前应换
Argon2/bcrypt 这类慢哈希。
- 登录返回的 `token` 目前**没有任何接口校验**,受保护路由实际尚未真正鉴权(见
`issue_token` 注释)。加鉴权中间件时再赋予其真实含义。