# 注册功能说明文档 ## 功能概述 系统支持三种注册方式: 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. 记录注册日志用于分析