431 lines
10 KiB
Markdown
431 lines
10 KiB
Markdown
# 注册功能说明文档
|
||
|
||
## 功能概述
|
||
|
||
系统支持三种注册方式:
|
||
1. **用户名注册** - 直接使用用户名+密码注册
|
||
2. **手机号注册** - 使用手机号+验证码+密码注册
|
||
3. **邮箱注册** - 使用邮箱+验证码+密码注册
|
||
|
||
## API接口
|
||
|
||
### 接口地址
|
||
```
|
||
POST /auth/register
|
||
```
|
||
|
||
### 请求参数
|
||
|
||
#### 通用参数
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| registerType | String | 是 | 注册类型:username/phone/email |
|
||
| password | String | 是 | 密码(至少6个字符) |
|
||
| confirmPassword | String | 是 | 确认密码 |
|
||
| studentId | String | 否 | 学号 |
|
||
|
||
#### 用户名注册 (registerType=username)
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| username | String | 是 | 用户名(3-20字符,仅字母数字下划线) |
|
||
|
||
#### 手机号注册 (registerType=phone)
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| phone | String | 是 | 手机号(11位中国手机号) |
|
||
| smsCode | String | 是 | 手机验证码(6位数字) |
|
||
|
||
#### 邮箱注册 (registerType=email)
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| email | String | 是 | 邮箱地址 |
|
||
| emailCode | String | 是 | 邮箱验证码(6位数字) |
|
||
|
||
### 请求示例
|
||
|
||
#### 1. 用户名注册
|
||
```json
|
||
{
|
||
"registerType": "username",
|
||
"username": "zhangsan",
|
||
"password": "123456",
|
||
"confirmPassword": "123456",
|
||
"studentId": "2021001"
|
||
}
|
||
```
|
||
|
||
#### 2. 手机号注册
|
||
```json
|
||
{
|
||
"registerType": "phone",
|
||
"phone": "13800138000",
|
||
"smsCode": "123456",
|
||
"password": "123456",
|
||
"confirmPassword": "123456",
|
||
"studentId": "2021001"
|
||
}
|
||
```
|
||
|
||
#### 3. 邮箱注册
|
||
```json
|
||
{
|
||
"registerType": "email",
|
||
"email": "user@example.com",
|
||
"emailCode": "123456",
|
||
"password": "123456",
|
||
"confirmPassword": "123456",
|
||
"studentId": "2021001"
|
||
}
|
||
```
|
||
|
||
### 响应结果
|
||
|
||
#### 注册成功
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "注册成功",
|
||
"data": {
|
||
"user": {
|
||
"ID": "xxx",
|
||
"username": "zhangsan",
|
||
"email": "user@example.com",
|
||
"phone": "13800138000",
|
||
"status": 0
|
||
},
|
||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
"loginTime": "2025-11-03T10:30:00",
|
||
"ipAddress": "127.0.0.1"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 注册失败
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"message": "用户已存在",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
## 业务流程
|
||
|
||
### 1. 用户名注册流程
|
||
```
|
||
用户输入用户名和密码
|
||
↓
|
||
验证用户名格式(3-20字符,字母数字下划线)
|
||
↓
|
||
验证密码(至少6字符,两次输入一致)
|
||
↓
|
||
检查用户名是否已存在
|
||
↓
|
||
密码加密(BCrypt)
|
||
↓
|
||
创建用户账号
|
||
↓
|
||
自动登录并返回token
|
||
```
|
||
|
||
### 2. 手机号注册流程
|
||
```
|
||
用户输入手机号
|
||
↓
|
||
点击"获取验证码"按钮
|
||
↓
|
||
系统发送短信验证码(60秒限制)
|
||
↓
|
||
用户输入验证码和密码
|
||
↓
|
||
验证手机号格式
|
||
↓
|
||
验证验证码(10分钟有效期)
|
||
↓
|
||
检查手机号是否已注册
|
||
↓
|
||
密码加密(BCrypt)
|
||
↓
|
||
创建用户账号(用户名=手机号)
|
||
↓
|
||
删除验证码(防止重复使用)
|
||
↓
|
||
自动登录并返回token
|
||
```
|
||
|
||
### 3. 邮箱注册流程
|
||
```
|
||
用户输入邮箱
|
||
↓
|
||
点击"获取验证码"按钮
|
||
↓
|
||
系统发送邮件验证码(60秒限制)
|
||
↓
|
||
用户输入验证码和密码
|
||
↓
|
||
验证邮箱格式
|
||
↓
|
||
验证验证码(10分钟有效期)
|
||
↓
|
||
检查邮箱是否已注册
|
||
↓
|
||
密码加密(BCrypt)
|
||
↓
|
||
创建用户账号(用户名=邮箱前缀)
|
||
↓
|
||
删除验证码(防止重复使用)
|
||
↓
|
||
自动登录并返回token
|
||
```
|
||
|
||
## 安全机制
|
||
|
||
### 1. 密码加密
|
||
- 使用 BCryptPasswordEncoder 进行密码加密
|
||
- 不可逆加密,安全性高
|
||
- 每次加密结果不同(内置salt)
|
||
|
||
### 2. 验证码机制
|
||
- **有效期**:10分钟
|
||
- **发送频率**:60秒只能发送一次
|
||
- **一次性使用**:验证后立即删除
|
||
- **存储位置**:Redis
|
||
- 手机验证码:`sms:code:手机号`
|
||
- 邮箱验证码:`email:code:邮箱`
|
||
|
||
### 3. 用户唯一性校验
|
||
通过UserService.registerUser内部实现:
|
||
- 检查用户名是否重复
|
||
- 检查手机号是否重复
|
||
- 检查邮箱是否重复
|
||
|
||
### 4. 注册后自动登录
|
||
- 注册成功后自动调用登录接口
|
||
- 返回完整的登录信息(token、用户信息等)
|
||
- 用户无需再次输入密码
|
||
|
||
## 数据库设计
|
||
|
||
### 用户表 (tb_sys_user)
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| ID | VARCHAR | 用户ID(主键) |
|
||
| username | VARCHAR | 用户名 |
|
||
| password | VARCHAR | 加密后的密码 |
|
||
| email | VARCHAR | 邮箱 |
|
||
| phone | VARCHAR | 手机号 |
|
||
| wechatID | VARCHAR | 微信号 |
|
||
| status | INT | 用户状态(0-正常,1-禁用,2-锁定) |
|
||
| createTime | DATETIME | 创建时间 |
|
||
| updateTime | DATETIME | 更新时间 |
|
||
| deleted | BOOLEAN | 是否删除 |
|
||
|
||
### 用户信息表 (tb_sys_user_info)
|
||
- 与用户表一对一关系
|
||
- 存储用户详细信息(头像、性别、姓名等)
|
||
- 注册时自动创建默认记录
|
||
|
||
## 错误码说明
|
||
|
||
| 错误码 | 错误信息 | 说明 |
|
||
|--------|----------|------|
|
||
| 500 | 密码不能为空 | 密码字段为空 |
|
||
| 500 | 密码至少6个字符 | 密码长度不足 |
|
||
| 500 | 两次输入的密码不一致 | 密码和确认密码不匹配 |
|
||
| 500 | 用户名不能为空 | 用户名注册时用户名为空 |
|
||
| 500 | 用户名长度为3-20个字符 | 用户名长度不符合要求 |
|
||
| 500 | 用户名只能包含字母、数字和下划线 | 用户名包含非法字符 |
|
||
| 500 | 手机号不能为空 | 手机号注册时手机号为空 |
|
||
| 500 | 手机号格式不正确 | 手机号格式错误 |
|
||
| 500 | 请输入手机验证码 | 手机验证码为空 |
|
||
| 500 | 验证码已过期,请重新获取 | 验证码不存在或已过期 |
|
||
| 500 | 验证码错误 | 验证码不正确 |
|
||
| 500 | 邮箱不能为空 | 邮箱注册时邮箱为空 |
|
||
| 500 | 邮箱格式不正确 | 邮箱格式错误 |
|
||
| 500 | 请输入邮箱验证码 | 邮箱验证码为空 |
|
||
| 500 | 用户已存在 | 用户名/手机号/邮箱已被注册 |
|
||
| 500 | 未知的注册类型 | registerType参数错误 |
|
||
|
||
## 前端集成示例
|
||
|
||
### 1. 用户名注册
|
||
```typescript
|
||
import { authApi } from '@/apis/system/auth';
|
||
|
||
const handleRegister = async () => {
|
||
const result = await authApi.register({
|
||
registerType: 'username',
|
||
username: 'zhangsan',
|
||
password: '123456',
|
||
confirmPassword: '123456',
|
||
agree: true
|
||
});
|
||
|
||
if (result.code === 200) {
|
||
// 注册成功,保存token
|
||
localStorage.setItem('token', result.data.token);
|
||
// 跳转到首页
|
||
router.push('/');
|
||
}
|
||
};
|
||
```
|
||
|
||
### 2. 手机号注册
|
||
```typescript
|
||
// 发送验证码
|
||
const sendSmsCode = async () => {
|
||
const result = await authApi.sendSmsCode('13800138000');
|
||
if (result.code === 200) {
|
||
ElMessage.success('验证码已发送');
|
||
// 开始倒计时
|
||
startCountdown();
|
||
}
|
||
};
|
||
|
||
// 注册
|
||
const handleRegister = async () => {
|
||
const result = await authApi.register({
|
||
registerType: 'phone',
|
||
phone: '13800138000',
|
||
smsCode: '123456',
|
||
password: '123456',
|
||
confirmPassword: '123456',
|
||
agree: true
|
||
});
|
||
|
||
if (result.code === 200) {
|
||
ElMessage.success('注册成功');
|
||
// 保存token并跳转
|
||
}
|
||
};
|
||
```
|
||
|
||
### 3. 邮箱注册
|
||
```typescript
|
||
// 发送验证码
|
||
const sendEmailCode = async () => {
|
||
const result = await authApi.sendEmailCode('user@example.com');
|
||
if (result.code === 200) {
|
||
ElMessage.success('验证码已发送到邮箱');
|
||
// 开始倒计时
|
||
startCountdown();
|
||
}
|
||
};
|
||
|
||
// 注册
|
||
const handleRegister = async () => {
|
||
const result = await authApi.register({
|
||
registerType: 'email',
|
||
email: 'user@example.com',
|
||
emailCode: '123456',
|
||
password: '123456',
|
||
confirmPassword: '123456',
|
||
agree: true
|
||
});
|
||
|
||
if (result.code === 200) {
|
||
ElMessage.success('注册成功');
|
||
// 保存token并跳转
|
||
}
|
||
};
|
||
```
|
||
|
||
## 测试用例
|
||
|
||
### 1. 用户名注册测试
|
||
```bash
|
||
# 正常注册
|
||
curl -X POST http://localhost:8081/schoolNewsServ/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"registerType": "username",
|
||
"username": "testuser",
|
||
"password": "123456",
|
||
"confirmPassword": "123456"
|
||
}'
|
||
|
||
# 用户名重复
|
||
curl -X POST http://localhost:8081/schoolNewsServ/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"registerType": "username",
|
||
"username": "testuser",
|
||
"password": "123456",
|
||
"confirmPassword": "123456"
|
||
}'
|
||
# 预期:返回"用户已存在"
|
||
|
||
# 用户名过短
|
||
curl -X POST http://localhost:8081/schoolNewsServ/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"registerType": "username",
|
||
"username": "ab",
|
||
"password": "123456",
|
||
"confirmPassword": "123456"
|
||
}'
|
||
# 预期:返回"用户名长度为3-20个字符"
|
||
```
|
||
|
||
### 2. 手机号注册测试
|
||
```bash
|
||
# 先发送验证码
|
||
curl -X POST http://localhost:8081/schoolNewsServ/auth/send-sms-code \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"phone": "13800138000"}'
|
||
|
||
# 然后注册(使用日志中的验证码)
|
||
curl -X POST http://localhost:8081/schoolNewsServ/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"registerType": "phone",
|
||
"phone": "13800138000",
|
||
"smsCode": "123456",
|
||
"password": "123456",
|
||
"confirmPassword": "123456"
|
||
}'
|
||
```
|
||
|
||
### 3. 邮箱注册测试
|
||
```bash
|
||
# 先发送验证码
|
||
curl -X POST http://localhost:8081/schoolNewsServ/auth/send-email-code \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"email": "test@example.com"}'
|
||
|
||
# 然后注册(检查邮箱获取验证码)
|
||
curl -X POST http://localhost:8081/schoolNewsServ/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"registerType": "email",
|
||
"email": "test@example.com",
|
||
"emailCode": "123456",
|
||
"password": "123456",
|
||
"confirmPassword": "123456"
|
||
}'
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **验证码有效期**:验证码10分钟后失效,需要重新获取
|
||
2. **发送频率限制**:同一手机号/邮箱60秒内只能发送一次验证码
|
||
3. **密码安全**:密码使用BCrypt加密存储,不可逆
|
||
4. **自动登录**:注册成功后自动登录,前端需要保存返回的token
|
||
5. **用户名规则**:
|
||
- 用户名注册:用户自定义
|
||
- 手机号注册:用户名=手机号
|
||
- 邮箱注册:用户名=邮箱前缀
|
||
6. **开发测试**:短信服务使用模拟模式时,验证码会在日志中输出
|
||
|
||
## 后续优化建议
|
||
|
||
1. 添加图形验证码,防止恶意发送验证码
|
||
2. 添加IP限流,防止批量注册
|
||
3. 添加邀请码机制
|
||
4. 实现手机号和邮箱的绑定功能
|
||
5. 添加密码强度验证
|
||
6. 实现找回密码功能
|
||
7. 添加注册协议弹窗确认
|
||
8. 记录注册日志用于分析
|
||
|