文章目录
- 用户认证系统实现文档
-
- [1. 概述](#1. 概述)
-
- [1.1 功能需求](#1.1 功能需求)
- [1.2 技术栈](#1.2 技术栈)
- [2. 架构设计](#2. 架构设计)
-
- [2.1 整体架构](#2.1 整体架构)
- [2.2 模块职责](#2.2 模块职责)
- [3. 数据模型设计](#3. 数据模型设计)
-
- [3.1 用户表结构](#3.1 用户表结构)
- [3.2 User 结构体](#3.2 User 结构体)
- [4. API 接口设计](#4. API 接口设计)
-
- [4.1 接口列表](#4.1 接口列表)
- [4.2 接口详细说明](#4.2 接口详细说明)
-
- [4.2.1 发送验证码](#4.2.1 发送验证码)
- [4.2.2 验证验证码](#4.2.2 验证验证码)
- [4.2.3 用户注册](#4.2.3 用户注册)
- [4.2.4 用户登录](#4.2.4 用户登录)
- [5. 核心实现](#5. 核心实现)
-
- [5.1 邮件发送模块](#5.1 邮件发送模块)
- [5.2 SHA256 哈希模块](#5.2 SHA256 哈希模块)
- [5.3 用户模型模块](#5.3 用户模型模块)
- [5.4 用户控制器模块](#5.4 用户控制器模块)
- [5.5 服务器路由配置](#5.5 服务器路由配置)
- [6. 前端实现](#6. 前端实现)
-
- [6.1 登录页面](#6.1 登录页面)
- [6.2 注册页面](#6.2 注册页面)
- [7. 安全措施](#7. 安全措施)
-
- [7.1 密码安全](#7.1 密码安全)
- [7.2 验证码安全](#7.2 验证码安全)
- [7.3 输入验证](#7.3 输入验证)
- [7.4 其他安全措施](#7.4 其他安全措施)
- [8. 部署与运行](#8. 部署与运行)
-
- [8.1 依赖安装](#8.1 依赖安装)
- [8.2 编译命令](#8.2 编译命令)
- [8.3 启动服务](#8.3 启动服务)
- [8.4 数据库初始化](#8.4 数据库初始化)
- [9. 编译问题与修复](#9. 编译问题与修复)
-
- [9.1 问题列表](#9.1 问题列表)
- [9.2 修复详情](#9.2 修复详情)
- [10. 测试方案](#10. 测试方案)
-
- [10.1 单元测试](#10.1 单元测试)
- [10.2 集成测试](#10.2 集成测试)
- [10.3 边界测试](#10.3 边界测试)
- [11. 未来优化](#11. 未来优化)
-
- [11.1 功能扩展](#11.1 功能扩展)
- [11.2 性能优化](#11.2 性能优化)
- [11.3 安全增强](#11.3 安全增强)
- [12. 代码示例](#12. 代码示例)
-
- [12.1 发送邮件示例](#12.1 发送邮件示例)
- [12.2 用户注册示例](#12.2 用户注册示例)
- [12.3 用户登录示例](#12.3 用户登录示例)
- [13. 术语表](#13. 术语表)
- [14. 版本记录](#14. 版本记录)
用户认证系统实现文档
1. 概述
本文档详细描述了 CodeJudge 在线编程评测平台的用户认证系统实现方案,包括用户注册、登录、邮箱验证等核心功能。
1.1 功能需求
| 功能 | 描述 | 优先级 |
|---|---|---|
| 用户注册 | 支持邮箱注册,包含邮箱验证码验证 | 高 |
| 用户登录 | 支持用户名或邮箱登录 | 高 |
| 邮箱验证 | 注册时需验证邮箱有效性 | 高 |
| 密码安全 | 使用盐值+哈希加密存储 | 高 |
| 会话管理 | 登录状态保持 | 中 |
1.2 技术栈
| 分类 | 技术 | 版本 |
|---|---|---|
| 语言 | C++ | 14 |
| Web框架 | httplib | 0.11.x |
| 数据库 | MySQL | 8.0+ |
| JSON处理 | jsoncpp | 1.9.x |
| 邮件发送 | libcurl | 7.x |
| 加密库 | OpenSSL | 3.0+ |
| 模板引擎 | ctemplate | 2.4.x |
2. 架构设计
2.1 整体架构
┌─────────────────────────────────────────────────────────────┐
│ 客户端 (Browser) │
├─────────────────────────────────────────────────────────────┤
│ /login /register /api/* │
└───────────────┬─────────────────────┬───────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ HTTP Server (httplib) │
│ ┌───────────────────┐ ┌─────────────────────┐ │
│ │ Oj_Control │ │ User_Control │ │
│ │ (题目业务逻辑) │ │ (用户认证逻辑) │ │
│ └─────────┬─────────┘ └──────────┬──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────────┐ ┌─────────────────────┐ │
│ │ Oj_Model │ │ User_Model │ │
│ │ (题目数据模型) │ │ (用户数据模型) │ │
│ └─────────┬─────────┘ └──────────┬──────────┘ │
│ │ │ │
│ └───────────┬───────────┘ │
│ ▼ │
│ ┌───────────────────┐ │
│ │ MySQL 数据库 │ │
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────────┘
2.2 模块职责
| 模块 | 文件 | 职责 |
|---|---|---|
| EmailSender | comm/email_sender.hpp |
SMTP邮件发送封装,支持SSL/TLS |
| StringUtil | comm/util.hpp |
字符串处理,包含SHA256哈希函数 |
| User_Model | oj_server/user_model.hpp |
用户数据模型与数据库操作 |
| User_Control | oj_server/user_control.hpp |
用户认证业务逻辑与API处理 |
| Server | oj_server/oj_server.cc |
HTTP路由注册与服务启动 |
3. 数据模型设计
3.1 用户表结构
sql
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户ID',
username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
email VARCHAR(100) NOT NULL UNIQUE COMMENT '邮箱地址',
password VARCHAR(255) NOT NULL COMMENT '加密后的密码(SHA256)',
salt VARCHAR(32) NOT NULL COMMENT '密码盐值(32位随机字符串)',
email_verified BOOLEAN DEFAULT FALSE COMMENT '邮箱是否已验证',
verify_code VARCHAR(6) COMMENT '邮箱验证码(6位数字)',
code_expire_time DATETIME COMMENT '验证码过期时间',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
last_login TIMESTAMP NULL COMMENT '最后登录时间',
INDEX idx_username (username),
INDEX idx_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
3.2 User 结构体
cpp
struct User {
int _id; // 用户ID
std::string _username; // 用户名
std::string _email; // 邮箱
std::string _password; // 加密密码(SHA256)
std::string _salt; // 盐值(32位)
bool _email_verified; // 邮箱验证状态
std::string _verify_code; // 验证码
std::string _code_expire_time; // 过期时间
std::string _created_at; // 创建时间
std::string _last_login; // 最后登录时间
};
4. API 接口设计
4.1 接口列表
| API | 方法 | 路径 | 描述 |
|---|---|---|---|
| 发送验证码 | POST | /api/send_code |
向指定邮箱发送6位验证码 |
| 验证验证码 | POST | /api/verify_code |
验证邮箱验证码正确性 |
| 用户注册 | POST | /api/register |
完成用户注册(需先验证验证码) |
| 用户登录 | POST | /api/login |
用户登录验证(支持用户名或邮箱) |
4.2 接口详细说明
4.2.1 发送验证码
请求:
json
POST /api/send_code
Content-Type: application/json
{
"email": "user@example.com"
}
响应:
json
{
"status": 0,
"message": "验证码已发送,有效期5分钟"
}
业务逻辑:
- 验证邮箱格式是否有效
- 检查邮箱是否已注册
- 生成6位随机验证码
- 保存验证码到数据库(5分钟有效期)
- 通过SMTP发送验证邮件
状态码:
0- 成功-1- 邮箱格式错误-2- 邮箱已注册-3- 邮件发送失败
4.2.2 验证验证码
请求:
json
POST /api/verify_code
Content-Type: application/json
{
"email": "user@example.com",
"code": "123456"
}
响应:
json
{
"status": 0,
"message": "验证成功"
}
业务逻辑:
- 验证邮箱和验证码格式
- 查询数据库中的验证码
- 检查验证码是否过期
- 验证验证码是否匹配
状态码:
0- 验证成功-1- 验证码错误-2- 验证码已过期-3- 邮箱未找到
4.2.3 用户注册
请求:
json
POST /api/register
Content-Type: application/json
{
"username": "user123",
"email": "user@example.com",
"code": "123456",
"password": "password123",
"confirm_password": "password123"
}
响应:
json
{
"status": 0,
"message": "注册成功"
}
验证规则:
| 字段 | 规则 |
|---|---|
| username | 3-20字符,仅字母、数字、下划线 |
| 有效邮箱格式 | |
| code | 6位数字 |
| password | 至少6字符 |
| confirm_password | 与password一致 |
状态码:
0- 注册成功-1- 参数验证失败-2- 验证码错误或过期-3- 用户名已存在-4- 邮箱已注册
4.2.4 用户登录
请求:
json
POST /api/login
Content-Type: application/json
{
"username_or_email": "user123",
"password": "password123"
}
响应:
json
{
"status": 0,
"message": "登录成功",
"user_id": 1,
"username": "user123",
"email": "user@example.com"
}
业务逻辑:
- 根据用户名或邮箱查询用户
- 获取存储的密码哈希和盐值
- 使用相同盐值对输入密码进行哈希
- 比对哈希值验证密码正确性
- 更新最后登录时间
状态码:
0- 登录成功-1- 用户不存在-2- 密码错误
5. 核心实现
5.1 邮件发送模块
文件 :comm/email_sender.hpp
核心功能:
- 基于 libcurl 实现 SMTP 协议
- 支持 SSL/TLS 加密连接(端口465)
- 支持中文邮件主题(Base64编码)
关键代码解析:
cpp
// 构建完整的邮件内容
std::string email_data;
email_data += "From: \"CodeJudge\" <" + _username + ">\r\n";
email_data += "To: <" + to + ">\r\n";
// 邮件主题使用 Base64 编码以支持中文
email_data += "Subject: =?UTF-8?B?" + Base64Encode(subject) + "?=\r\n";
email_data += "Content-Type: text/plain; charset=UTF-8\r\n";
email_data += "\r\n"; // 空行分隔头部和正文
email_data += body;
QQ邮箱配置:
cpp
// QQ SMTP 服务器配置
std::string smtp_server = "smtp.qq.com";
int smtp_port = 465; // SSL端口
std::string username = "3502173090@qq.com";
std::string password = "uuxrrvvqudqvchia"; // 授权码(非登录密码)
兼容性修复 :
由于 C++11 不支持 std::make_unique,使用 new 替代:
cpp
// C++11 兼容的智能指针创建方式
return std::unique_ptr<EmailSender>(new EmailSender("smtp.qq.com", 465, username, auth_code, true));
5.2 SHA256 哈希模块
文件 :comm/util.hpp
核心功能:
- 使用 OpenSSL 3.0 EVP 接口实现 SHA256 哈希
- 返回64位十六进制字符串
- 兼容 OpenSSL 3.0+ 版本
关键代码解析:
cpp
static std::string SHA256(const std::string& input) {
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len = 0;
// 使用 OpenSSL 3.0 EVP 接口(避免旧API弃用警告)
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
if (!ctx) return "";
// 初始化 SHA256 上下文
EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr);
// 更新哈希值
EVP_DigestUpdate(ctx, input.c_str(), input.size());
// 完成哈希计算
EVP_DigestFinal_ex(ctx, hash, &hash_len);
// 释放上下文
EVP_MD_CTX_free(ctx);
// 转换为十六进制字符串
std::stringstream ss;
for(unsigned int i = 0; i < hash_len; i++) {
ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
}
return ss.str();
}
设计要点:
- 使用 EVP 接口而非旧版 SHA256_Init/Update/Final 函数
- 避免 OpenSSL 3.0 弃用警告
- 正确处理内存释放(EVP_MD_CTX_free)
5.3 用户模型模块
文件 :oj_server/user_model.hpp
核心功能:
| 方法 | 功能 |
|---|---|
GenerateSalt() |
生成32位随机盐值 |
GenerateVerifyCode() |
生成6位数字验证码 |
HashPassword() |
SHA256密码加密(密码+盐值) |
SendVerifyCode() |
发送验证码邮件 |
VerifyEmailCode() |
验证验证码有效性 |
CompleteRegister() |
完成用户注册 |
Login() |
用户登录验证 |
验证码生成算法:
cpp
std::string GenerateVerifyCode() const {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(100000, 999999);
return std::to_string(dis(gen));
}
密码加密流程:
cpp
// 注册时:生成盐值并加密
std::string salt = GenerateSalt(); // 32位随机字符串
std::string hash_password = StringUtil::SHA256(password + salt);
// 登录验证时:使用存储的盐值重新计算
std::string input_hash = StringUtil::SHA256(input_password + stored_salt);
if (input_hash == stored_hash) {
// 验证通过
}
安全设计:
- 每个用户独立盐值,防止彩虹表攻击
- 密码存储为哈希值,不存储明文
- 盐值与密码一起哈希,增加破解难度
5.4 用户控制器模块
文件 :oj_server/user_control.hpp
核心职责:
- 接收请求并解析 JSON
- 数据验证(格式、长度、逻辑)
- 调用 Model 层执行业务逻辑
- 生成统一格式的 JSON 响应
验证流程:
请求 → JSON解析 → 参数验证 → 业务逻辑 → 生成响应
示例:注册验证逻辑
cpp
bool HandleRegister(const std::string &in_json, std::string *out_json) {
// 1. JSON解析
Json::Value in_value;
Json::Reader reader;
reader.parse(in_json, in_value);
// 2. 参数提取
std::string username = in_value["username"].asString();
std::string email = in_value["email"].asString();
std::string code = in_value["code"].asString();
std::string password = in_value["password"].asString();
std::string confirm_password = in_value["confirm_password"].asString();
// 3. 参数验证(前端+后端双重验证)
if (username.size() < 3 || username.size() > 20) {
*out_json = "{\"status\":-1, \"message\":\"用户名长度必须在3-20个字符之间\"}";
return false;
}
// 4. 验证码验证
if (!_model.VerifyEmailCode(email, code)) {
*out_json = "{\"status\":-2, \"message\":\"验证码错误或已过期\"}";
return false;
}
// 5. 完成注册
if (_model.CompleteRegister(email, username, password)) {
*out_json = "{\"status\":0, \"message\":\"注册成功\"}";
return true;
} else {
*out_json = "{\"status\":-3, \"message\":\"注册失败\"}";
return false;
}
}
5.5 服务器路由配置
文件 :oj_server/oj_server.cc
路由注册:
cpp
// API接口路由
svr.Post("/api/send_code", [&user_ctl](const Request &req, Response &resp){
std::string result_json;
user_ctl.HandleSendCode(req.body, &result_json);
resp.set_content(result_json, "application/json;charset=utf-8");
});
svr.Post("/api/verify_code", [&user_ctl](const Request &req, Response &resp){
std::string result_json;
user_ctl.HandleVerifyCode(req.body, &result_json);
resp.set_content(result_json, "application/json;charset=utf-8");
});
svr.Post("/api/register", [&user_ctl](const Request &req, Response &resp){
std::string result_json;
user_ctl.HandleRegister(req.body, &result_json);
resp.set_content(result_json, "application/json;charset=utf-8");
});
svr.Post("/api/login", [&user_ctl](const Request &req, Response &resp){
std::string result_json;
user_ctl.HandleLogin(req.body, &result_json);
resp.set_content(result_json, "application/json;charset=utf-8");
});
// 页面路由
svr.Get("/login", [](const Request &req, Response &resp){
std::string html;
FileUtil::ReadFile("../wwwroot/login.html", &html, true);
resp.set_content(html, "text/html;charset=utf-8");
});
svr.Get("/register", [](const Request &req, Response &resp){
std::string html;
FileUtil::ReadFile("../wwwroot/register.html", &html, true);
resp.set_content(html, "text/html;charset=utf-8");
});
6. 前端实现
6.1 登录页面
文件 :wwwroot/login.html
功能特性:
- 响应式设计,支持移动端
- 表单验证(前端+后端)
- 错误/成功消息提示
- 第三方登录入口(预留)
核心 JavaScript:
javascript
form.addEventListener('submit', function(e) {
e.preventDefault();
// 获取用户输入
const username_or_email = document.getElementById('username_or_email').value;
const password = document.getElementById('password').value;
// 发送登录请求
fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username_or_email: username_or_email,
password: password
})
})
.then(response => response.json())
.then(data => {
if (data.status === 0) {
// 登录成功:保存用户信息到本地存储
localStorage.setItem('user_id', data.user_id);
localStorage.setItem('username', data.username);
localStorage.setItem('email', data.email);
localStorage.setItem('is_logged_in', 'true');
// 跳转到首页
setTimeout(() => {
window.location.href = '/';
}, 1500);
} else {
// 登录失败:显示错误信息
errorMsg.textContent = data.message;
errorMsg.style.display = 'block';
}
});
});
6.2 注册页面
文件 :wwwroot/register.html
功能特性:
- 邮箱验证码发送(60秒发送间隔限制)
- 表单实时验证
- 密码强度提示
- 两次密码确认
验证码发送逻辑:
javascript
sendCodeBtn.addEventListener('click', function() {
const email = emailInput.value;
// 前端验证邮箱格式
if (!email.includes('@') || !email.includes('.')) {
errorMsg.textContent = '请输入有效的邮箱地址';
return;
}
// 发送请求
fetch('/api/send_code', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: email })
})
.then(response => response.json())
.then(data => {
if (data.status === 0) {
// 发送成功:开始60秒倒计时
countdown = 60;
sendCodeBtn.disabled = true;
sendCodeBtn.textContent = `${countdown}s后重新发送`;
timer = setInterval(() => {
countdown--;
if (countdown <= 0) {
clearInterval(timer);
sendCodeBtn.disabled = false;
sendCodeBtn.textContent = '发送验证码';
} else {
sendCodeBtn.textContent = `${countdown}s后重新发送`;
}
}, 1000);
}
});
});
7. 安全措施
7.1 密码安全
| 措施 | 说明 |
|---|---|
| 盐值加密 | 每个用户独立32位随机盐值 |
| SHA256哈希 | 密码+盐值双重加密,生成64位哈希值 |
| 禁止明文存储 | 数据库仅存储哈希值,不存储原始密码 |
7.2 验证码安全
| 措施 | 说明 |
|---|---|
| 5分钟有效期 | 验证码超时自动失效 |
| 60秒发送间隔 | 防止恶意刷取验证码 |
| 一次性使用 | 验证成功后立即失效 |
7.3 输入验证
| 措施 | 说明 |
|---|---|
| 前端验证 | 即时反馈,减轻服务器压力 |
| 后端验证 | 最终验证,防止绕过前端验证 |
| 格式检查 | 邮箱、用户名格式校验 |
| 长度限制 | 防止超长输入攻击 |
7.4 其他安全措施
| 措施 | 说明 |
|---|---|
| HTTPS | 生产环境强制使用,加密传输 |
| 日志记录 | 关键操作记录审计 |
| 授权码机制 | 邮箱SMTP使用授权码而非登录密码 |
| SQL注入防护 | 参数验证与格式检查 |
8. 部署与运行
8.1 依赖安装
bash
# 安装基础依赖
sudo apt-get update
sudo apt-get install -y libcurl4-openssl-dev libjsoncpp-dev libmysqlclient-dev
# 安装 OpenSSL(SHA256依赖)
sudo apt-get install -y libssl-dev
# 安装 ctemplate(模板引擎)
sudo apt-get install -y libctemplate-dev
8.2 编译命令
bash
cd oj_server
make clean
make
Makefile 配置:
makefile
oj_server: oj_server.cc
g++ -o $@ $^ -std=c++14 -lctemplate -ljsoncpp -lmysqlclient -lcrypto -lcurl
.PHONY: clean
clean:
rm -rf oj_server
链接库说明:
| 库 | 用途 |
|---|---|
-lctemplate |
模板引擎 |
-ljsoncpp |
JSON处理 |
-lmysqlclient |
MySQL数据库 |
-lcrypto |
SHA256哈希(OpenSSL) |
-lcurl |
SMTP邮件发送 |
8.3 启动服务
bash
./oj_server
服务将在 http://localhost:8080 启动。
8.4 数据库初始化
sql
-- 创建数据库
CREATE DATABASE IF NOT EXISTS oj CHARACTER SET utf8mb4;
-- 使用数据库
USE oj;
-- 创建用户表
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
salt VARCHAR(32) NOT NULL,
email_verified BOOLEAN DEFAULT FALSE,
verify_code VARCHAR(6),
code_expire_time DATETIME,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP NULL
);
9. 编译问题与修复
9.1 问题列表
| 问题 | 原因 | 修复方案 |
|---|---|---|
std::make_unique 未定义 |
C++11 不支持该函数 | 使用 new 替代 make_unique |
StringUtil::SHA256 未定义 |
函数不存在 | 在 util.hpp 中添加该函数 |
| OpenSSL 3.0 弃用警告 | 旧API已弃用 | 使用 EVP 接口替代旧版 SHA256 API |
| 链接错误 | 缺少必要的链接库 | 添加 -lcrypto -lcurl |
9.2 修复详情
问题1:std::make_unique 兼容性
cpp
// 修复前(C++14+)
return std::make_unique<EmailSender>("smtp.qq.com", 465, username, auth_code, true);
// 修复后(兼容C++11)
return std::unique_ptr<EmailSender>(new EmailSender("smtp.qq.com", 465, username, auth_code, true));
问题2:SHA256 函数缺失
在 comm/util.hpp 的 StringUtil 类中添加:
cpp
static std::string SHA256(const std::string& input) {
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len = 0;
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
if (!ctx) return "";
EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr);
EVP_DigestUpdate(ctx, input.c_str(), input.size());
EVP_DigestFinal_ex(ctx, hash, &hash_len);
EVP_MD_CTX_free(ctx);
std::stringstream ss;
for(unsigned int i = 0; i < hash_len; i++) {
ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
}
return ss.str();
}
问题3:Makefile 链接库
makefile
# 修复前
g++ -o oj_server oj_server.cc -std=c++14 -lctemplate -ljsoncpp -lmysqlclient
# 修复后
g++ -o oj_server oj_server.cc -std=c++14 -lctemplate -ljsoncpp -lmysqlclient -lcrypto -lcurl
10. 测试方案
10.1 单元测试
| 测试项 | 测试方法 | 预期结果 |
|---|---|---|
| 用户名验证 | 输入3-20字符 | 验证通过 |
| 用户名验证 | 输入特殊字符 | 验证失败 |
| 邮箱格式 | 有效邮箱 | 验证通过 |
| 邮箱格式 | 无效邮箱 | 验证失败 |
| 验证码生成 | 调用生成函数 | 返回6位数字 |
| 密码加密 | 相同密码+相同盐 | 相同哈希值 |
10.2 集成测试
| 测试场景 | 步骤 | 预期结果 |
|---|---|---|
| 注册流程 | 输入邮箱→获取验证码→输入信息→注册 | 注册成功 |
| 登录流程 | 输入账号密码→登录 | 登录成功,跳转首页 |
| 验证码过期 | 获取验证码→等待5分钟→验证 | 验证码过期提示 |
| 重复注册 | 使用已注册邮箱 | 提示邮箱已注册 |
10.3 边界测试
| 边界情况 | 测试方法 | 预期结果 |
|---|---|---|
| 空输入 | 提交空表单 | 提示必填字段 |
| 超长输入 | 用户名21字符 | 提示长度超限 |
| 错误验证码 | 输入错误6位数字 | 提示验证码错误 |
| 网络异常 | 断网状态提交 | 提示网络错误 |
11. 未来优化
11.1 功能扩展
| 功能 | 描述 | 优先级 |
|---|---|---|
| 忘记密码 | 通过邮箱重置密码 | 高 |
| 第三方登录 | GitHub/Google OAuth | 中 |
| 用户资料 | 头像、昵称修改 | 中 |
| 会话管理 | JWT Token实现 | 高 |
11.2 性能优化
| 优化项 | 描述 |
|---|---|
| 连接池 | MySQL连接复用 |
| 缓存 | 用户信息Redis缓存 |
| 异步邮件 | 消息队列异步发送 |
11.3 安全增强
| 措施 | 描述 |
|---|---|
| 限流 | API请求频率限制 |
| 验证码图形化 | 防止自动识别 |
| 双因素认证 | 登录二次验证 |
| SQL预处理 | 防止SQL注入 |
12. 代码示例
12.1 发送邮件示例
cpp
#include "comm/email_sender.hpp"
int main() {
// 创建QQ邮箱发送器(使用授权码)
auto sender = ns_email::CreateQQEmailSender("3502173090@qq.com", "uuxrrvvqudqvchia");
// 发送邮件
bool success = sender->SendEmail(
"user@example.com",
"CodeJudge 邮箱验证",
"您的验证码是:123456\n有效期5分钟"
);
std::cout << (success ? "发送成功" : "发送失败") << std::endl;
return 0;
}
12.2 用户注册示例
bash
curl -X POST http://localhost:8080/api/register \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"email": "test@example.com",
"code": "123456",
"password": "password123",
"confirm_password": "password123"
}'
12.3 用户登录示例
bash
curl -X POST http://localhost:8080/api/login \
-H "Content-Type: application/json" \
-d '{
"username_or_email": "testuser",
"password": "password123"
}'
13. 术语表
| 术语 | 定义 |
|---|---|
| SMTP | Simple Mail Transfer Protocol,邮件传输协议 |
| SHA256 | 安全哈希算法,生成256位哈希值 |
| Salt | 盐值,随机字符串用于增强密码安全性 |
| JWT | JSON Web Token,用于身份认证的令牌 |
| OAuth | 开放授权协议,用于第三方登录 |
| CSRF | 跨站请求伪造,一种安全攻击方式 |
| XSS | 跨站脚本攻击,一种安全攻击方式 |
| EVP | OpenSSL 加密接口,提供统一的加密算法调用方式 |
14. 版本记录
| 版本 | 日期 | 修改内容 | 作者 |
|---|---|---|---|
| v1.0 | 2026-05-11 | 初始版本,实现基础注册登录功能 | SSKL |
| v1.1 | 2026-05-12 | 添加邮箱验证码功能 | SSKL |
| v1.2 | 2026-05-13 | 修复编译问题(make_unique、SHA256) | SSKL |