173 lines
8.2 KiB
Markdown
173 lines
8.2 KiB
Markdown
# 账号管理功能 - 设计文档
|
||
|
||
## 1. 功能描述
|
||
本模块负责处理所有用户的认证与基础账户操作,包括注册、登录和安全设置(如忘记密码、修改密码/手机号)。其核心目标是提供一个安全、可靠且用户体验良好的身份验证入口。
|
||
|
||
## 2. 涉及角色
|
||
- **所有角色**: 该功能是所有需要登录系统的用户(公众监督员、监督员、网格员、管理员、决策者)的通用基础功能。
|
||
|
||
## 3. 业务规则
|
||
|
||
### 3.1 注册规则
|
||
- **唯一性约束**: 注册时使用的`邮箱`和`手机号`必须在`user_account`表中是唯一的。
|
||
- **密码策略**:
|
||
- 复杂度: 8-16位,必须同时包含大写字母、小写字母、数字和特殊字符。
|
||
- 确认机制: 注册时密码需要输入两次进行确认。
|
||
- 存储安全: 密码在后端必须使用强哈希算法(如BCrypt)加盐后存储,绝不允许明文存储。
|
||
- **邮箱验证码规则**:
|
||
- **时效性**: 验证码生成后5分钟内有效。
|
||
- **冷却期**: "获取验证码"按钮点击后,有60秒的冷却时间,防止恶意请求。
|
||
- **尝试次数**: 同一个验证码最多允许输错2次,第3次输错则该验证码立即失效,需重新获取。
|
||
|
||
### 3.2 登录规则
|
||
- 支持使用`邮箱`或`手机号`作为登录凭据。
|
||
- 登录失败时,应给出统一的、模糊的提示(如"用户名或密码错误"),避免泄露账户是否存在的信息。
|
||
- 可考虑引入登录尝试次数限制机制,例如连续失败5次后,临时锁定账户15分钟。
|
||
|
||
### 3.3 安全验证规则
|
||
- **身份确认**: "忘记密码"或"修改手机号"等敏感操作,必须先通过"邮箱 + 姓名"进行第一步身份确认。
|
||
- **操作授权**: 身份确认通过后,必须再次完成与注册流程完全相同的邮箱动态验证码校验,才能进行下一步操作。
|
||
|
||
### 3.4 JWT (Token) 规则
|
||
- **Payload 结构**: Token的Payload中应至少包含`userId`, `role`, `email`,以便后端进行快速的身份和权限识别。
|
||
- **有效期**: Access Token的有效期应设置为较短的时间(如1小时),以降低泄露风险。
|
||
- **刷新机制**: 提供一个Refresh Token,其有效期更长(如7天)。当Access Token过期后,前端可使用Refresh Token向后端申请新的Access Token,无需用户重新登录。
|
||
- **存储**: 前端应将Access Token存储在内存中,将Refresh Token存储在`HttpOnly`、`Secure`的Cookie中,以提高安全性。
|
||
|
||
### 3.5 系统管理员操作规则
|
||
- **创建内部账户**: 系统管理员(Admin)在NEPM端创建内部用户(如`SUPERVISOR`, `GRID_WORKER`)时,系统应生成一个安全的初始随机密码。
|
||
- **密码重置**: 管理员可以为任何用户重置密码,重置后同样生成一个随机密码。
|
||
- **密码分发**: 生成的初始密码或重置后的密码,应通过安全的、非系统内的方式(如邮件、短信)告知用户,并强制用户在首次登录后立即修改。
|
||
|
||
## 4. 功能实现流程
|
||
|
||
### 4.1 注册流程
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 用户
|
||
participant Frontend as 前端界面
|
||
participant Backend as 后端服务
|
||
participant Mail as 邮箱服务
|
||
|
||
User->>Frontend: 填写注册信息 (邮箱, 手机, 密码等)
|
||
Note right of Frontend: 前端实时校验格式和密码强度
|
||
User->>Frontend: 点击"获取验证码"
|
||
Frontend->>Backend: POST /api/auth/send-verification-code
|
||
Note over Backend: 生成6位验证码, 存入Redis并设5分钟过期
|
||
Backend->>Mail: 调用163邮箱API发送验证码
|
||
Mail-->>User: 收到验证码邮件
|
||
User->>Frontend: 输入收到的验证码
|
||
User->>Frontend: 点击"注册"
|
||
Frontend->>Backend: POST /api/auth/register
|
||
Backend->>Backend: 校验验证码 (正确性, 是否过期, 尝试次数)
|
||
alt 验证成功
|
||
Backend->>Backend: 校验邮箱/手机唯一性, BCrypt加密密码
|
||
Backend->>Backend: 创建`user_account`记录
|
||
Backend-->>Frontend: 注册成功 (201 Created)
|
||
else 验证失败
|
||
Backend-->>Frontend: 返回错误信息 (400 Bad Request)
|
||
end
|
||
```
|
||
|
||
### 4.2 登录流程
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 用户
|
||
participant Frontend as 前端
|
||
participant Backend as 后端
|
||
|
||
User->>Frontend: 输入邮箱/手机号和密码, 点击登录
|
||
Frontend->>Backend: POST /api/auth/login
|
||
Backend->>Backend: 验证用户信息和密码
|
||
alt 验证成功
|
||
Backend->>Backend: 生成Access Token和Refresh Token
|
||
Backend-->>Frontend: 登录成功 (200 OK)<br>返回Access Token, 并设置Refresh Token到Cookie
|
||
Note left of Frontend: 存储Token, 跳转到用户主页
|
||
else 验证失败
|
||
Backend->>Backend: 记录失败次数, 检查是否需要锁定账户
|
||
Backend-->>Frontend: 返回"用户名或密码错误" (401 Unauthorized)
|
||
end
|
||
```
|
||
|
||
### 4.3 忘记密码流程
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 用户
|
||
participant Frontend as 前端界面
|
||
participant Backend as 后端服务
|
||
|
||
User->>Frontend: 点击"忘记密码", 输入邮箱和姓名
|
||
Frontend->>Backend: POST /api/auth/request-password-reset
|
||
Backend->>Backend: 校验邮箱和姓名是否存在且匹配
|
||
alt 身份校验成功
|
||
Backend-->>Frontend: 跳转至邮箱验证码页面
|
||
Note right of Frontend: (后续流程与注册时的邮箱验证完全相同)
|
||
User->>Frontend: 完成邮箱验证, 输入新密码
|
||
Frontend->>Backend: POST /api/auth/reset-password
|
||
Backend->>Backend: 更新用户密码
|
||
Backend-->>Frontend: 密码重置成功 (200 OK)
|
||
else 身份校验失败
|
||
Backend-->>Frontend: 返回错误信息 (400 Bad Request)
|
||
end
|
||
```
|
||
|
||
## 5. API 接口设计
|
||
|
||
### 5.1 用户注册
|
||
- **URL**: `POST /api/auth/register`
|
||
- **请求体**: `name`, `email`, `phone`, `password`, `verificationCode`
|
||
- **响应**: `201 Created`
|
||
|
||
### 5.2 用户登录
|
||
- **URL**: `POST /api/auth/login`
|
||
- **请求体**: `principal` (邮箱或手机号), `password`
|
||
- **响应**: `200 OK`, 返回 `accessToken`,并在Cookie中设置`refreshToken`。
|
||
|
||
### 5.3 发送邮箱验证码
|
||
- **URL**: `POST /api/auth/send-verification-code`
|
||
- **请求体**: `email`, `type` (Enum: `REGISTER`, `RESET_PASSWORD`)
|
||
- **响应**: `200 OK`
|
||
|
||
### 5.4 刷新AccessToken
|
||
- **URL**: `POST /api/auth/refresh-token`
|
||
- **请求体**: (空, Refresh Token从Cookie中获取)
|
||
- **响应**: `200 OK`, 返回新的`accessToken`。
|
||
|
||
### 5.5 请求密码重置
|
||
- **URL**: `POST /api/auth/request-password-reset`
|
||
- **请求体**: `email`, `name`
|
||
- **响应**: `200 OK` (无论用户是否存在,都返回成功,防止信息泄露)
|
||
|
||
### 5.6 重置密码
|
||
- **URL**: `POST /api/auth/reset-password`
|
||
- **请求体**: `email`, `newPassword`, `verificationCode`
|
||
- **响应**: `200 OK`
|
||
|
||
### 5.7 管理员创建用户
|
||
- **URL**: `POST /api/admin/users`
|
||
- **权限**: `ADMIN`
|
||
- **请求体**: `name`, `email`, `phone`, `role`, `region`, `level`
|
||
- **响应**: `201 Created`, 返回包含初始随机密码的用户信息。
|
||
|
||
## 6. 界面设计要求
|
||
|
||
### 6.1 注册页面
|
||
- 表单布局清晰,各输入项有明确的标签和占位提示。
|
||
- "获取验证码"按钮在点击后应变为不可用状态,并显示倒计时。
|
||
- 密码输入框应为密码类型,并提供一个可切换"显示/隐藏"密码的图标。
|
||
- 密码强度提示:实时根据用户输入,以进度条或文字形式提示密码强度(弱、中、强)。
|
||
- 所有输入项的错误提示应在输入框下方实时显示,内容明确。
|
||
|
||
### 6.2 登录页面
|
||
- 界面简洁,突出登录表单。
|
||
- 提供"忘记密码"的链接。
|
||
- 可选提供"记住我"的复选框。
|
||
- 登录成功后,应有平滑的过渡效果,并根据用户角色跳转到对应的系统主页(NEPS, NEPG, NEPM, NEPV)。
|
||
|
||
### 6.3 忘记密码/安全验证页面
|
||
- 流程应分步进行,保持每一步操作的单一和清晰。
|
||
- 第一步:身份验证(输入邮箱、姓名)。
|
||
- 第二步:安全验证(输入邮箱收到的验证码)。
|
||
- 第三步:重置密码(输入新密码并确认)。
|
||
- 每个步骤都应有清晰的标题和进度指示。
|
||
- 操作成功后,应明确提示用户"密码已重置,请使用新密码登录",并引导至登录页面。 |