1、完善注册/登录

1. 涉及的数据库表单:user_info

2. 引用MySQL线程池,Redis线程池

3. 完善注册功能

4. 完善登录功能

2.1 涉及的数据库表单:user_info

重新创建数据库

#创建数据库
DROP DATABASE IF EXISTS `0voice_tuchuang`;CREATE DATABASE `0voice_tuchuang`;
#使用数据库
use `0voice_tuchuang`;

先清楚user表(如果存在) ,然后重新创建表单

# 清除表单
DROP TABLE IF EXISTS `user_info`;
# 重新创建表单 id自增,nick_name user_name创建唯一索引
CREATE TABLE `user_info` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户序号,自动递增,主键',`user_name` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名称',`nick_name` varchar(32) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '用户昵称',`password` varchar(32) NOT NULL DEFAULT '' COMMENT '密码',`phone` varchar(16) NOT NULL DEFAULT '' COMMENT '手机号码',`email` varchar(64) DEFAULT '' COMMENT '邮箱',`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '时间',PRIMARY KEY (`id`),UNIQUE KEY `uq_nick_name` (`nick_name`),UNIQUE KEY `uq_user_name` (`user_name`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='用户信息表';

这样就新增了用户表单。

2.2 引入MySQL线程池,Redis线程池

redis mysql目录为MySQL redis操作接口。

MySQL连接池,目前设置了master,slave两个连接池,master用于有写的操作,slave用于读的操作,通 过指定连接池获取连接示例代码:

CDBManager *db_manager = CDBManager::getInstance(); //这里用了单例模式
//从slave数据库读取数据(目前实际上主从都是同一个,后续可以使用主从方式测试对比性能)
CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave"); //指定连接池
AUTO_REL_DBCONN(db_manager, db_conn); //退出当前函数时自动把连接归还连接池

Redis连接池,目前设置了token,ranking_list两个连接池,token用于token的读写,ranking_list用于下载 排行榜的操作,通过指定连接池获取连接示例代码:

CacheManager *cache_manager = CacheManager::getInstance();
CacheConn *cache_conn = cache_manager->GetCacheConn("token");//指定连接池
AUTO_REL_CACHECONN(cache_manager, cache_conn); //退出当前函数时自动把连接归还连接池

2.3 实现完整的注册功能

1. 部分头文件以及通用函数 放到新建的api_common.h api_common.cc

2. 调用MySQL操作接口

3. 重点是api_register.cc的代码完善

引用MySQL操作接口

#include "db_pool.h" // 相关的MySQL操作接口的头文件

/*
* 先根据用户名查询数据库该用户是否存在,不存在才插入
*/
int registerUser(string &user_name, string &nick_name, string &pwd, string &phone, string &email) {int ret = 0;uint32_t user_id;CDBManager *db_manager = CDBManager::getInstance(); //这里用了单例模式//从slave数据库读取数据(目前实际上主从都是同一个,后续可以使用主从方式测试对比性能)CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn);// 先查看用户是否存在string str_sql = FormatString("select id, user_name from user_info where user_name='%s'", user_name.c_str());CResultSet *result_set = db_conn->ExecuteQuery(str_sql.c_str());if (result_set && result_set->Next()) { // 检测是否存在用户记录// 存在在返回LOG_WARN << "id: " << result_set->GetInt("id") << ", user_name: " << result_set->GetString("user_name")<< " 已经存在";delete result_set;ret = 2; // 说明用户已经存在了} else { // 如果不存在则注册time_t now;char create_time[TIME_STRING_LEN];//获取当前时间now = time(NULL);strftime(create_time, TIME_STRING_LEN - 1, "%Y-%m-%d %H:%M:%S", localtime(&now));str_sql = "insert into user_info ""(`user_name`,`nick_name`,`password`,`phone`,`email`,`create_""time`) values(?,?,?,?,?,?)";LOG_INFO << "执行: " << str_sql;// 必须在释放连接前delete// CPrepareStatement对象,否则有可能多个线程操作mysql对象,会crash// 预处理方式写入数据CPrepareStatement *stmt = new CPrepareStatement();if (stmt->Init(db_conn->GetMysql(), str_sql)) {uint32_t index = 0;string c_time = create_time;stmt->SetParam(index++, user_name);stmt->SetParam(index++, nick_name);stmt->SetParam(index++, pwd);stmt->SetParam(index++, phone);stmt->SetParam(index++, email);stmt->SetParam(index++, c_time);bool bRet = stmt->ExecuteUpdate(); //真正提交要写入的数据if (bRet) { //提交正常返回 trueret = 0;user_id = db_conn->GetInsertId();LOG_INFO << "insert user_id: " << user_id;} else {LOG_ERROR << "insert user_info failed. " << str_sql;ret = 1;}}delete stmt;}return ret;
}

2.4 实现完整的登录功能

主要是完善:

  • verifyUserPassword(string &user_name, string &pwd) 函数,通过用户名查询数据库对应的密码,对 比请求登录的密码是否一致
  • setToken(string &user_name, string &token) 如果一致则 生成一个新token,并以token为key,用户 名作为value,把token存储到redis里。

2.4.1 校验用户名密码verifyUserPassword

int verifyUserPassword(string &user_name, string &pwd) {int ret = 0;CDBManager *db_manager = CDBManager::getInstance();CDBConn *db_conn = db_manager->GetDBConn("tuchuang_slave");AUTO_REL_DBCONN(db_manager, db_conn); //析构时自动归还连接// 根据用户名查询密码string strSql = FormatString("select password from user_info where user_name='%s'", user_name.c_str());CResultSet *result_set = db_conn->ExecuteQuery(strSql.c_str());if (result_set && result_set->Next()) { //如果存在则读取密码// 存在在返回string password = result_set->GetString("password");LOG_INFO << "mysql-pwd: " << password << ", user-pwd: " << pwd;if (password == pwd) //对比密码是否一致ret = 0; //对比成功elseret = -1; //对比失败} else { // 说明用户不存在ret = -1;}delete result_set;return ret;
}

2.4.2 使用redis实现token验证机制

Redis是一个开源的内存数据存储系统,可以用作数据库、缓存和消息中间件。它支持多种数据结构,例如字 符串、哈希、列表、集合和有序集合。Redis通过将数据存储在内存中,提供了非常高效的读写速度。

在Web应用程序中,使用Redis存储Token有以下几个优点:

  • 快速:Redis的数据存储在内存中,读写速度非常快,适用于高并发的场景。
  • 可扩展性:Redis支持分布式部署,可以轻松实现横向扩展。
  • 多种数据结构:Redis支持多种数据结构,可以根据需求选择适合的数据结构存储Token。
  • 过期时间管理:Redis提供了设置过期时间的功能,可以轻松实现Token的自动过期和续期。

因为我们使用token作为key,所以需要做到唯一,所以也就需要通过算法生成唯一的key,我们使用libuuid 这个库。

Ubuntu安装:

sudo apt-get install uuid-dev

使用方式:

头文件引用 #include

CMakeLists.txt要:

包含路径:INCLUDE_DIRECTORIES(/usr/include)

包含库文件目录:LINK_DIRECTORIES(/usr/lib)

包含库的引用 uuid:TARGET_LINK_LIBRARIES(tc_http_srv3 .... uuid)

调用uuid的接口封装generateUUID:

std::string generateUUID() {uuid_t uuid;uuid_generate_time_safe(uuid); //调用uuid的接口char uuidStr[40] = {0};uuid_unparse(uuid, uuidStr); //调用uuid的接口return std::string(uuidStr);
}

在redis设置token

int setToken(string &user_name, string &token) {int ret = 0;CacheManager *cache_manager = CacheManager::getInstance();CacheConn *cache_conn = cache_manager->GetCacheConn("token");AUTO_REL_CACHECONN(cache_manager, cache_conn);token = generateUUID(); // 生成唯一的tokenif (cache_conn) {//token - 用户名, 86400有效时间为24小时 有效期可以自己修改cache_conn->SetEx(token, 86400, user_name); // redis做超时} else {ret = -1;}return ret;
}

校验token和user_name

//验证登陆token,成功返回0,失败-1
int VerifyToken(string &user_name, string &token) {int ret = 0;CacheManager *cache_manager = CacheManager::getInstance();CacheConn *cache_conn = cache_manager->GetCacheConn("token");AUTO_REL_CACHECONN(cache_manager, cache_conn);if (cache_conn) {string temp_user_name = cache_conn->Get(token); //校验token和用户名的关系if (temp_user_name == user_name) {ret = 0;} else {ret = -1;}} else {ret = -1;}return ret;
}

参考连接:https://github.com/0voice

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94248.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94248.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/94248.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux文件系统】目录结构

有没有刚进入Linux世界时&#xff0c;对着黑乎乎的终端&#xff0c;输入一个 ls / 后&#xff0c;看着蹦出来的一堆名字 like bin, etc, usr&#xff0c;感觉一头雾水&#xff0c;像是在看天书&#xff1f; 别担心&#xff0c;你不是一个人。Linux的文件系统就像一个超级有条理…

螺旋槽曲面方程的数学建模与偏导数求解

螺旋槽曲面的数学描述 在钻头设计和机械加工领域,螺旋槽的几何建模至关重要。螺旋槽通常由径向截形绕轴做螺旋运动形成,其数学模型可通过参数方程和隐函数方程两种方式描述。 设螺旋槽的径向截形方程为: y=f(z)y = f(z)y=f(z) x=xcx = x_cx=xc​ 其中 xcx_cxc​ 为常数,…

线性回归:机器学习中的基石

在机器学习的众多算法中&#xff0c;线性回归无疑是最基础也是最常被提及的一种。它不仅在统计学中占有重要地位&#xff0c;而且在预测分析和数据建模中也发挥着关键作用。本文将深入探讨线性回归的基本概念、评估指标以及在实际问题中的应用&#xff0c;并通过一个模拟的气象…

编程刷题-资料分发1 图论/DFS

P2097 资料分发 1 题目描述 有一些电脑&#xff0c;一部分电脑有双向数据线连接。 如果一个电脑得到数据&#xff0c;它可以传送到的电脑都可以得到数据。 现在&#xff0c;你有这个数据&#xff0c;问你至少将其输入几台电脑&#xff0c;才能使所有电脑得到数据。 输入格式 第…

RabbitMQ:延时消息(死信交换机、延迟消息插件)

目录一、死信交换机【不推荐】二、延迟消息插件【推荐】2.1 安装插件【Linux】2.2 安装插件【Windows】2.3 如何使用延时消息&#xff1a;生产者发送消息时指定一个时间&#xff0c;消费者不会立刻收到消息&#xff0c;而是在指定时间之后才收到消息。 延时任务&#xff1a;设置…

动学学深度学习05-深度学习计算

动学学深度学习pytorch 参考地址&#xff1a;https://zh.d2l.ai/ 文章目录动学学深度学习pytorch1-第05章-深度学习计算1. 层&#xff08;Layer&#xff09;与块&#xff08;Block&#xff09;1.1 什么是深度学习中的“层”&#xff1f;1.2 什么是“块”&#xff08;Block&…

智慧工厂烟雾检测:全场景覆盖与精准防控

智慧工厂烟雾检测&#xff1a;构建工业安全的智能防线&#xff08;所有图片均为真实项目案例&#xff09;在工业4.0时代&#xff0c;智慧工厂通过物联网、人工智能与大数据技术的深度融合&#xff0c;实现了生产流程的数字化与智能化。然而&#xff0c;工厂环境中的火灾隐患始终…

@JsonIgnoreProperties注解详解

JsonIgnoreProperties是 Jackson 库中的一个重要注解&#xff0c;用于在 JSON 序列化&#xff08;对象转 JSON&#xff09;和反序列化&#xff08;JSON 转对象&#xff09;过程中​​控制属性的可见性​​。它提供了更高级别的属性忽略能力&#xff0c;特别适合处理复杂场景。一…

红酒数据集预处理实战:缺失值处理的 5 种打开方式,从入门到进阶一步到位

在数据分析与建模流程中&#xff0c;缺失值处理是数据预处理阶段的关键步骤&#xff0c;直接影响后续模型的准确性与稳定性。本文以红酒数据集为研究对象&#xff0c;详细介绍如何通过基础统计方法&#xff08;均值、中位数、众数&#xff09;、完整案例分析&#xff08;CCA&am…

Node.js 开发 JavaScript SDK 包的完整指南(AI)

一、核心概念SDK 包定义 专为特定服务/平台封装的工具库&#xff0c;提供标准化 API 调用、错误处理、类型声明等功能。示例&#xff1a;支付宝 SDK、AWS SDK、微信小程序 SDK。技术栈选择 语言&#xff1a;JavaScript/TypeScript&#xff08;推荐 TS&#xff0c;便于类型提示&…

Redis实战-基于Session实现分布式登录

1.流程分析1.1发送短信验证码提交手机号的时候要进行校验手机号&#xff0c;校验成功才会去生成验证码&#xff0c;将验证码保存到session&#xff0c;发生他把这部分那。1.2短信验证码登录/注册如果提交手机号和验证码之后&#xff0c;校验一致才进行根据手机号查询用户&#…

疯狂星期四文案网第47天运营日记

网站运营第47天&#xff0c;点击观站&#xff1a; 疯狂星期四 crazy-thursday.com 全网最全的疯狂星期四文案网站 运营报告 今日访问量 今日搜索引擎收录情况 必应现在是边收录边k页面 百度快倒闭 网站优化点 完善工作流&#xff0c;全面实现文案自动化采集&#xff0c;se…

Vue生命周期以及自定义钩子和路由

Vue生命周期常用的onMounted挂载后执行和onUnmounted卸载前以及onupdated更新后实际上用react对比就是useEffect&#xff0c;而且挂载顺序也是子组件先于父组件然后往外的栈结构&#xff0c;先进后出。1.Vue的生命周期<template><h2>当前求和为{{ sum }}</h2>…

探索Thompson Shell:Unix初代Shell的智慧

引言 在计算机科学的漫漫长河中&#xff0c;Thompson Shell 无疑占据着举足轻重的开创性地位&#xff0c;它是 Unix 系统的第一个 shell&#xff0c;诞生于 1971 年&#xff0c;由计算机领域的传奇人物 Ken Thompson 开发。在那个计算机技术刚刚起步、硬件资源极度匮乏的年代&a…

MySQL B+ 树索引详解:从原理到实战优化

引言在现代数据库应用中&#xff0c;查询效率是影响系统性能的关键因素之一。而索引&#xff0c;尤其是 B 树索引&#xff0c;是 MySQL 中最常用、最重要的性能优化手段。正确使用索引可以将查询时间从毫秒级降低到微秒级&#xff0c;极大地提升应用响应速度。1. B 树索引的重要…

计算机内存中的整型存储奥秘、大小端字节序及其判断方法

目录 一、回顾与引入&#xff1a;整数在内存中的存储方式 为什么要采用补码存储&#xff1f; 二、大小端字节序及其判断方法 1、什么是大小端&#xff1f; 2、为什么存在大小端&#xff1f; 3、练习 练习1&#xff1a;简述大小端概念并设计判断程序&#xff08;百度面试…

Redis 最常用的 5 种数据类型

Redis 支持多种灵活的数据类型&#xff0c;每种类型针对特定场景优化。以下是 **Redis 最常用的 5 种数据类型**及其核心特点和应用场景&#xff1a;1. 字符串&#xff08;String&#xff09;描述&#xff1a;最基本的数据类型&#xff0c;可存储文本、数字&#xff08;整数/浮…

【嵌入式】RK3588 对比 NVIDIA Jetson,Radxa Rock 5B vs Orange Pi 5 Max

RK3588这个芯片,适合AI应用么,为什么这么贵呢 AI 边缘盒子里的旗舰芯 深度分析一下 RK3588(瑞芯微 Rockchip RK3588) 为什么被很多人关注在 AI 应用,以及它价格偏高的原因。 🧩 1. RK3588 的基本情况 制程:8nm(Samsung 8nm LP) CPU:8 核 big.LITTLE 架构(4 Cortex-…

暴雨让高性能计算更“冷静”

当AI大模型的参数突破万亿&#xff0c;当深地探测的精度迈向微米&#xff0c;当数字经济的脉搏与千行百业深度共振&#xff0c;算力已成为驱动时代向前的核心引擎。然而&#xff0c;传统风冷技术在高密度算力需求面前渐显乏力——机柜内的热浪如同无形的枷锁&#xff0c;既制约…

SpringAI集成MCP

文章目录1_调用公用MCP2_Stdio方式3_Stdio实现原理4_SSE方式5_自定义MCP客户端6_MCP Server权限控制SpringAI 通过 SpringBoot 集成扩展了 MCP Java SDK &#xff0c;提供了客户端和服务端 starter&#xff0c;让 AI 应用程序快速支持 MCP。接下来直接演示。 1_调用公用MCP 在…