11.1.3 完善注冊登錄,實現文件上傳和展示

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 在…