WebServer -- 注冊登錄

目錄

🍉整體內容

🌼流程圖

🎂載入數據庫表

提取用戶名和密碼

🚩同步線程登錄注冊

補充解釋

代碼

😘頁面跳轉

補充解釋

代碼


🍉整體內容

概述

TinyWebServer 中,使用數據庫連接池實現服務器訪問數據庫的功能,使用 POST請求 完成 注冊和登錄的校驗工作

內容

本博客介紹同步實現注冊登錄功能,具體涉及:流程圖,載入數據庫表,提取用戶名和密碼,注冊登錄流程,以及頁面跳轉的代碼實現

  • 流程圖
    服務器從報文中提取用戶名密碼,接著,完成注冊登錄校驗后,實現頁面跳轉邏輯
  • 載入數據庫表
    將數據庫的數據載入服務器
  • 提取用戶名和密碼
    解析報文,提取用戶名和密碼
  • 注冊登錄流程
    描述服務器注冊和登錄校驗的流程
  • 頁面跳轉
    詳解頁面跳轉機制

🌼流程圖

具體地,描述了 GET 和 POST 請求下的頁面跳轉流程👇

🎂載入數據庫表

將數據庫的用戶名和密碼,載入服務器的 map 中,map中,key是用戶名,value是密碼

// 用戶名和密碼
map<string, string> users;void http_conn::initmysql_result(connection_pool *connPool)
{// 先從連接池取一個連接MYSQL *mysql = NULL;connectionRAII mysqlcon(&mysql, connPool); // 利用connectionRAII封裝的RAII機制獲取數據庫連接// 在 user 表中檢索username, passwd數據,瀏覽器輸入if (mysql_query(mysql, "SELECT username,passwd FROM user")) // 執行查詢語句{LOG_ERROR("SELECT error:%s\n", mysql_error(mysql)); // 輸出錯誤信息}// 表中檢索完整的結果集MYSQL_RES *result = mysql_store_result(mysql); // 存儲查詢結果// 返回結果集中的列數int num_fields = mysql_num_fields(result); // 獲取結果集中列的數量// 返回所有字段結構的數組MYSQL_FIELD *fields = mysql_fetch_fields(result); // 獲取結果集中所有字段的信息// 從結果集獲取下一行,將對應用戶名和密碼,存入 mapwhile (MYSQL_ROW row = mysql_fetch_row(result)) // 迭代每一行數據{string temp1(row[0]); // 提取用戶名string temp2(row[1]); // 提取密碼users[temp1] = temp2; // 將用戶名和密碼存入map中}
}

提取用戶名和密碼

服務器解析瀏覽器的請求報文,當解析為POST請求時,cgi 標志位設置為1,并將請求報文的消息體賦值給 m_string,進而提取出用戶名和密碼

// 用戶名和密碼
map<string, string> users;void http_conn::initmysql_result(connection_pool *connPool)
{// 先從連接池取一個連接MYSQL *mysql = NULL;connectionRAII mysqlcon(&mysql, connPool); // 利用connectionRAII封裝的RAII機制獲取數據庫連接// 在 user 表中檢索username, passwd數據,瀏覽器輸入if (mysql_query(mysql, "SELECT username,passwd FROM user")) // 執行查詢語句{LOG_ERROR("SELECT error:%s\n", mysql_error(mysql)); // 輸出錯誤信息}// 表中檢索完整的結果集MYSQL_RES *result = mysql_store_result(mysql); // 存儲查詢結果// 返回結果集中的列數int num_fields = mysql_num_fields(result); // 獲取結果集中列的數量// 返回所有字段結構的數組MYSQL_FIELD *fields = mysql_fetch_fields(result); // 獲取結果集中所有字段的信息// 從結果集獲取下一行,將對應用戶名和密碼,存入 mapwhile (MYSQL_ROW row = mysql_fetch_row(result)) // 迭代每一行數據{string temp1(row[0]); // 提取用戶名string temp2(row[1]); // 提取密碼users[temp1] = temp2; // 將用戶名和密碼存入map中}
}

🚩同步線程登錄注冊

通過 m_url 定位 / 所在位置,根據 / 后第一個字符,判斷是登錄還是注冊校驗

  • 2
    • 登錄校驗
  • 3
    • 注冊校驗

根據校驗結果,跳轉對應頁面;此外,對數據庫操作時,需要通過鎖來同步

補充解釋

  1. 首先通過解析URL判斷用戶是要進行注冊還是登錄操作,這是通過檢查URL中的下一個字符來實現的

  2. 如果是注冊操作,首先會檢查數據庫中是否已經存在相同的用戶名,如果不存在則向數據庫中插入新的用戶名和密碼,并在map中記錄該用戶的信息

  3. 如果是登錄操作,會直接在map中查找用戶輸入的用戶名和密碼,如果存在且匹配,則返回歡迎頁面,否則返回登錄錯誤頁面

  4. 無論是注冊還是登錄,操作完成后都會修改URL,將用戶重定向到相應的頁面,以提供反饋給用戶

std::strrchr - cppreference.com

👆返回字符串中,最后一次出現該字符的位置?

std::strcpy - cppreference.com

👆strcpy(dest, src)? ? ? ?src 復制到 dest

std::strcat - cppreference.com

👆strcat(dest, src)? ? ?src 追加到 dest 后

代碼

const char *p = strrchr(m_url, '/'); // 在字符串 m_url 中查找最后一次出現字符 '/' 的位置,并返回指向該位置的指針if (0 == m_SQLVerify) {if (*(p + 1) == '3') // 如果 URL 中的下一個字符是 '3'{// 如果是注冊,先檢測數據庫中是否有重名// 沒有重名,就增加數據char *sql_insert = (char *)malloc(sizeof(char) * 200); // 分配內存空間strcpy(sql_insert, "INSERT INTO user(username, passwd) VALUES("); // 拼接SQL語句strcat(sql_insert, "'"); // 拼接SQL語句strcat(sql_insert, name); // 拼接SQL語句strcat(sql_insert, "', '"); // 拼接SQL語句strcat(sql_insert, "password"); // 拼接SQL語句strcat(sql_insert, "')"); // 拼接SQL語句// 判斷 map 中能否找到重復的用戶名if (user.find(name) == users.end()) { // 如果在map中找不到重復的用戶名// 向數據庫插入數據時,需要通過鎖來同步數據m_lock.lock(); // 加鎖int res = mysql_query(mysql, sql_insert); // 執行SQL語句users.insert(pair<string, string>(name, password)); // 將用戶名和密碼插入map中m_lock.unlock(); // 解鎖// 校驗成功,跳轉登錄頁面if (!res)strcpy(m_url, "/log.html"); // 修改URL,跳轉至登錄頁面// 校驗失敗,跳轉注冊失敗頁面else strcpy(m_url, "/registerError.html"); // 修改URL,跳轉至注冊失敗頁面}else strcpy(m_url, "/registerError.html"); // 修改URL,跳轉至注冊失敗頁面}// 如果是登錄,直接判斷// 若瀏覽器輸入的用戶名和密碼在表中可以查找到,返回 1,否則返回 0else if (*(p + 1) == '2') { // 如果 URL 中的下一個字符是 '2'if (users.find(name) != users.end() && users[name]) // 如果在map中找到用戶名,并且密碼正確strcpy(m_url, "/welcome.html"); // 修改URL,跳轉至歡迎頁面elsestrcpy(m_url, "/logError.html"); // 修改URL,跳轉至登錄錯誤頁面}
}

😘頁面跳轉

通過 m_url 定位 / 所在位置,根據 / 后的第一個字符,使用分支語句實現頁面跳轉,具體👇

  • 0
    • 跳轉注冊頁面,GET
  • 1
    • 跳轉登錄頁面,GET
  • 5
    • 顯示圖片頁面,POST
  • 6
    • 顯示視頻頁面,POST
  • 7
    • 顯示關注頁面,POST

補充解釋

malloc - cppreference.com

1)👆動態分配內存

#include <stdio.h>
#include <stdlib.h>int main(void)
{int *p1 = malloc(4*sizeof(int));  // 分配足夠空間以存儲一個包含 4 個整數的數組int *p2 = malloc(sizeof(int[4])); // 同上,直接命名類型int *p3 = malloc(4*sizeof *p3);   // 同上,無需重復類型名稱if(p1) {for(int n=0; n<4; ++n) // 填充數組p1[n] = n*n;for(int n=0; n<4; ++n) // 打印數組內容printf("p1[%d] == %d\n", n, p1[n]);}free(p1); // 釋放動態分配的內存free(p2);free(p3);
}

std::strncpy - cppreference.com

2)👆char *strncpy(char *dest, const char *src, size_t n)

src 復制到 dest,最多賦值 n 個字符,如果 src 長度 < n,dest 剩余部分空字節 \0 填充

eg:

#include <cstring>
#include <iostream>int main()
{const char* src = "hi";char dest[6] = {'a', 'b', 'c', 'd', 'e', 'f'};std::strncpy(dest, src, 5);std::cout << "The contents of dest are: ";for (char c : dest){if (c)std::cout << c << ' ';elsestd::cout << "\\0" << ' ';}std::cout << '\n';
}

前 5 個字符被替換為 h i \0 \0 \0,第 6 個字符保留原來的 f

The contents of dest are: h i \0 \0 \0 f

代碼

// 找到 url 中 / 所在位置,進而判斷 / 后第一個字符
const char *p = strrchr(m_url, '/');// 注冊頁面
if (*(p + 1) == '0') {// 分配內存以存儲 URL 字符串,使用類型轉換將返回的指針轉換為 char 類型指針char *m_url_real = (char *)malloc(sizeof(char) * 200);strcpy(m_url_real, "/register.html");// 將注冊頁面的 URL 復制到實際文件路徑中strncpy(m_real_file + len, m_url_real, strlen(m_url_real));// 釋放內存free(m_url_real);
}// 登錄頁面
else if (*(p + 1) == '1') {char *m_url_real = (char *)malloc(sizeof(char) * 200);strcpy(m_url_real, "/log.html");// 將登錄頁面的 URL 復制到實際文件路徑中strncpy(m_real_file + len, m_url_real, strlen(m_url_real));// 釋放內存free(m_url_real);
}// 圖片頁面
else if (*(p + 1) == '5') {char *m_url_real = (char *)malloc(sizeof(char) * 200);strcpy(m_url_real, "/picture.html");// 將圖片頁面的 URL 復制到實際文件路徑中strncpy(m_real_file + len, m_url_real, strlen(m_url_real));// 釋放內存free(m_url_real);
}// 視頻頁面
else if (*(p + 1) == '6') {char *m_url_real = (char *)malloc(sizeof(char) * 200);strcpy(m_url_real, "/vedio.html");// 將視頻頁面的 URL 復制到實際文件路徑中strncpy(m_real_file + len, m_url_real, strlen(m_url_real));// 釋放內存free(m_url_real);
}// 關注頁面
else if (*(p + 1) == '7') {char *m_url_real = (char *)malloc(sizeof(char) * 200);strcpy(m_url_real, "/fans.html");// 將關注頁面的 URL 復制到實際文件路徑中strncpy(m_real_file + len, m_url_real, strlen(m_url_real));// 釋放內存free(m_url_real);
}// 否則發送 url 實際請求的文件
else// 將原始 URL 復制到實際文件路徑中strncpy(m_real_file + len, m_url, FILENAME_LEN - len - 1);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714927.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714927.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714927.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux 內核irq_stack遍歷

環境Centos 4.18.0-80.el8.x86_64 一、x86架構堆棧類型說明 https://www.kernel.org/doc/Documentation/x86/kernel-stacks int get_stack_info(unsigned long *stack, struct task_struct *task,struct stack_info *info, unsigned long *visit_mask) {if (!stack)goto unk…

【深度學習筆記】計算機視覺——圖像增廣

圖像增廣 sec_alexnet提到過大型數據集是成功應用深度神經網絡的先決條件。 圖像增廣在對訓練圖像進行一系列的隨機變化之后&#xff0c;生成相似但不同的訓練樣本&#xff0c;從而擴大了訓練集的規模。 此外&#xff0c;應用圖像增廣的原因是&#xff0c;隨機改變訓練樣本可以…

Python + Selenium —— 下拉菜單處理!

傳統的下拉菜單 Select 元素&#xff0c;由一個 Select 一系列的 option 元素構成。 <select id"source" name"source"><option value"">--請選擇--</option><option value"1001">網絡營銷</option>&…

3.3 序列式容器-deque、stack、queue、heap、priority_queue

deque 3.1定義 std::deque&#xff08;雙端隊列&#xff09;是C標準模板庫&#xff08;STL&#xff09;中的一種容器&#xff0c;表示雙端隊列數據結構。它提供了在兩端高效地進行插入和刪除操作的能力。與vector的連續線性空間類似&#xff0c;但有所不同&#xff0c;deque動…

基于ssm旅社客房收費管理系統+vue

目 錄 目 錄 I 摘 要 III ABSTRACT IV 1 緒論 1 1.1 課題背景 1 1.2 研究現狀 1 1.3 研究內容 2 2 系統開發環境 3 2.1 vue技術 3 2.2 JAVA技術 3 2.3 MYSQL數據庫 3 2.4 B/S結構 4 2.5 SSM框架技術 4 3 系統分析 5 3.1 可行性分析 5 3.1.1 技術可行性 5 3.1.2 操作可行性 5 3…

STM32使用FlyMcu串口下載程序與STLink Utility下載程序

文章目錄 前言軟件鏈接一、FlyMcu串口下載程序原理優化手動修改跳線帽選項字節其他功能 二、STLink Utility下載程序下載程序選項字節固件更新 前言 本文主要講解使用FlyMcu配合USART串口為STM32下載程序、使用STLink Utility配合STLink為STM32下載程序&#xff0c;以及這兩個…

代碼隨想錄算法訓練營第62/63天| 503.下一個更大元素II、42. 接雨水、84.柱狀圖中最大的矩形

文章目錄 503.下一個更大元素II思路代碼 42. 接雨水思路代碼 84.柱狀圖中最大的矩形思路代碼 503.下一個更大元素II 題目鏈接&#xff1a;503.下一個更大元素II 文章講解&#xff1a;代碼隨想錄|503.下一個更大元素II 思路 和739. 每日溫度 (opens new window)也幾乎如出一轍&…

C++/數據結構:AVL樹

目錄 一、AVL樹的概念 二、AVL樹的實現 2.1節點定義 2.2節點插入 三、AVL樹的旋轉 3.1新節點插入較高左子樹的左側&#xff1a;右單旋 3.2新節點插入較高右子樹的右側&#xff1a;左單旋 3.3新節點插入較高左子樹的右側---左右&#xff1a;先左單旋再右單旋 3.4新節點插…

Rocky Linux 運維工具 Systemd

一、Systemd 的簡介 Systemd是一個用于管理Linux系統啟動進程和服務的系統和服務管理器&#xff0c;取代了傳統的init系統。它提供了并行啟動、依賴關系管理、動態加載服務文件等功能&#xff0c;成為現代Linux發行版中主流的初始化系統。 二、Systemd 的參數說明 [Unit] Des…

SLAM基礎知識-卡爾曼濾波

前言&#xff1a; 在SLAM系統中&#xff0c;后端優化部分有兩大流派。一派是基于馬爾科夫性假設的濾波器方法&#xff0c;認為當前時刻的狀態只與上一時刻的狀態有關。另一派是非線性優化方法&#xff0c;認為當前時刻狀態應該結合之前所有時刻的狀態一起考慮。 卡爾曼濾波是…

SD NAND:為車載顯示器注入智能與安全的心臟

SD NAND 在車載顯示器的應用 在車載顯示器上&#xff0c;SD NAND&#xff08;Secure Digital NAND&#xff09;可以有多種應用&#xff0c;其中一些可能包括&#xff1a; 導航數據存儲&#xff1a; SD NAND 可以用于存儲地圖數據、導航軟件以及車載系統的相關信息。這有助于提…

微服務day03-Nacos配置管理與Nacos集群搭建

一.Nacos配置管理 Nacos不僅可以作為注冊中心&#xff0c;可以進行配置管理 1.1 統一配置管理 統一配置管理可以實現配置的熱更新&#xff08;即不用重啟當服務發生變更時也可以直接更新&#xff09; dataId格式&#xff1a;服務名-環境名.yaml&#xff0c;分組一般使用默認…

InnoDB高級特性篇(5)-使用InnoDB的全文索引

InnoDB是MySQL數據庫的一個關系型存儲引擎。它提供了很多強大的功能&#xff0c;其中一個重要的功能是全文索引。全文索引允許我們在文本數據中進行高效的搜索&#xff0c;以找到包含特定關鍵詞的記錄。在本文中&#xff0c;我們將詳細介紹如何在InnoDB中使用全文索引。 首先&…

藍橋杯備戰刷題two(自用)

1.楊輝三角形 #include<iostream> using namespace std; #define ll long long const int N2e510; int a[N]; //1 0 0 0 0 0 0 //1 1 0 0 0 0 0 //1 2 1 0 0 0 0 //1 3 3 1 0 0 0 //1 4 6 4 1 0 0 //1 5 10 10 5 1 //前綴和思想 //第一列全為1,第二列為從0開始遞增1的序…

信息檢索(七):Transformer Memory as a Differentiable Search Index

Transformer Memory as a Differentiable Search Index 摘要1. 引言2. 相關工作3. 可微搜索索引3.1 索引策略3.1.1 索引方法3.1.2 文檔表示策略 3.2 用于檢索的 Docids 表示3.3 訓練和優化 4. 實驗4.1 基線4.2 實驗結果 5. 結論參考資料 原文鏈接&#xff1a;https://proceedin…

Revit-二開之創建線性尺寸標注-(5)

創建線性尺寸標注 對應的Revit界面的按鈕 線性尺寸標注源碼 本篇文章實現的邏輯是從rvt文章中拾取一面墻,然后對墻添加再水平方向上的線性尺寸標注 protected override Result OnExecute(ExternalCommandData commandData, ref string message, ElementSet elements

LeetCode 刷題 [C++] 第55題.跳躍游戲

題目描述 給你一個非負整數數組 nums &#xff0c;你最初位于數組的 第一個下標 。數組中的每個元素代表你在該位置可以跳躍的最大長度。 判斷你是否能夠到達最后一個下標&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 題目分析 題目中…

2.1 mov、add和sub加減指令實操體驗

匯編語言 1. mov操作 1.1 mov移動值 mov指令把右邊的值移動到左邊 mount c d:masm c: debug r ax 0034 r 073f:0100 mov ax,7t1.2 mov移動寄存器的值 把右邊寄存器的值賦值給左邊的寄存器 a 073f:0105 mov bx,axt1.3 mov高八位&#xff08;high&#xff09;和低八位&am…

設計模式——中介者模式(mediator pattern)

概述 如果在一個系統中對象之間的聯系呈現為網狀結構&#xff0c;如下圖所示。對象之間存在大量的多對多聯系&#xff0c;將導致系統非常復雜&#xff0c;這些對象既會影響別的對象&#xff0c;也會被別的對象所影響&#xff0c;這些對象稱為同事對象&#xff0c;它們之間通過彼…

json---->如何把對象以json的形式傳遞給后端?

把對象以json的形式傳遞有很多種&#xff0c;先寫一種&#xff0c;后期再補充 &#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&#x1f64c;&…