3.7 KiB
3.7 KiB
用户账号系统设计
日期: 2026-06-15
状态: 已批准
背景
项目现状:Vue 前端 + Hono/Bun 后端 + SQLite,所有数据对任何人开放访问,无任何认证。目标是加入登录门禁,防止陌生人访问,但所有登录用户共享同一份数据。
核心决策
- 多用户账号,存数据库,管理员创建账号(不开放注册)
- access token(JWT,15分钟)+ refresh token(随机UUID入库,7天)双 token 方案
- refresh token hash 后存库,支持撤销
一、数据库 Schema
在现有 books 表旁新增两张表,在 server/db.ts 的 SCHEMA 中追加:
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'user',
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS refresh_tokens (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token_hash TEXT NOT NULL,
expires_at TEXT NOT NULL,
created_at TEXT NOT NULL
);
初始 admin 账号: 服务启动时读取环境变量 ADMIN_USERNAME / ADMIN_PASSWORD,若 users 表中不存在该用户名则自动写入。密码用 bcrypt hash 存储。
二、服务端 API
新增文件
server/auth.ts— JWT 签发/验证、bcrypt、token CRUD 的纯函数server/middleware/auth.ts— Hono 中间件(验证 Bearer token,注入 user 到 context)server/routes/auth.ts—/api/auth/*路由server/routes/admin.ts—/api/admin/*路由
端点列表
| 方法 | 路径 | 说明 | 认证要求 |
|---|---|---|---|
| POST | /api/auth/login |
登录,返回 access + refresh token | 无 |
| POST | /api/auth/refresh |
换新 access token | 无(带 refresh token) |
| POST | /api/auth/logout |
撤销当前 refresh token | Bearer |
| GET | /api/auth/me |
返回当前用户信息 | Bearer |
| GET | /api/admin/users |
列出所有用户 | Admin only |
| POST | /api/admin/users |
创建新用户 | Admin only |
| DELETE | /api/admin/users/:id |
删除用户 | Admin only |
现有路由保护
/api/books/* 和 /api/generate/* 全部加上 auth 中间件,未认证返回 401。
Token 规格
- access token:JWT,HS256,payload
{ userId, role, exp: now+15min },密钥来自环境变量JWT_SECRET - refresh token:
crypto.randomUUID(),SHA-256 hash 后存refresh_tokens表,原始值返回给客户端
三、前端
新增文件
src/composables/useAuth.ts— token 管理、登录/登出/刷新逻辑src/components/LoginPage.vue— 登录表单src/components/AdminPage.vue— 用户管理页(admin 专属)
修改文件
src/App.vue— 根据登录状态切换渲染 LoginPage 或主应用src/services/booksApi.ts— 所有请求加Authorizationheader,401 时触发 refresh
useAuth composable 行为
- localStorage 存
access_token和refresh_token - 导出:
isLoggedIn(computed)、user(ref)、login()、logout() - 提供
authedFetch()封装:自动带 token,遇 401 先尝试 refresh,refresh 失败则清除 token 跳登录页
AdminPage
- 仅当
user.role === 'admin'时在主界面显示入口 - 功能:列出所有用户、创建账号(用户名+密码)、删除账号(不能删除自己)
四、环境变量
.env 新增:
JWT_SECRET=<随机长字符串>
ADMIN_USERNAME=admin
ADMIN_PASSWORD=<初始密码>
五、依赖
jsonwebtoken或 Hono 自带的hono/jwt— JWT 操作bcryptjs— 密码 hash(纯 JS,兼容 Bun)
六、不在本次范围内
- 修改密码功能
- 邮件验证
- 多 admin 角色权限细分