当前位置: 首页 > news >正文

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);

相关文章:

WebServer -- 注册登录

目录 &#x1f349;整体内容 &#x1f33c;流程图 &#x1f382;载入数据库表 提取用户名和密码 &#x1f6a9;同步线程登录注册 补充解释 代码 &#x1f618;页面跳转 补充解释 代码 &#x1f349;整体内容 概述 TinyWebServer 中&#xff0c;使用数据库连接池实现…...

C3_W2_Collaborative_RecSys_Assignment_吴恩达_中英_Pytorch

Practice lab: Collaborative Filtering Recommender Systems(实践实验室:协同过滤推荐系统) In this exercise, you will implement collaborative filtering to build a recommender system for movies. 在本次实验中&#xff0c;你将实现协同过滤来构建一个电影推荐系统。 …...

Elasticsearch使用function_score查询酒店和排序

需求 基于用户地理位置&#xff0c;对酒店做简单的排序&#xff0c;非个性化的推荐。酒店评分包含以下&#xff1a; 酒店类型&#xff08;依赖用户历史订单数据&#xff09;&#xff1a;希望匹配出更加符合用户使用的酒店类型酒店评分&#xff1a;评分高的酒店用户体验感好ge…...

iOS消息发送流程

Objc的方法调用基于消息发送机制。即Objc中的方法调用&#xff0c;在底层实际都是通过调用objc_msgSend方法向对象消息发送消息来实现的。在iOS中&#xff0c; 实例对象的方法主要存储在类的方法列表中&#xff0c;类方法则是主要存储在原类中。 向对象发送消息&#xff0c;核心…...

【接口测试】常见HTTP面试题

目录 HTTP GET 和 POST 的区别 GET 和 POST 方法都是安全和幂等的吗 接口幂等实现方式 说说 post 请求的几种参数格式是什么样的&#xff1f; HTTP特性 HTTP&#xff08;1.1&#xff09; 的优点有哪些&#xff1f; HTTP&#xff08;1.1&#xff09; 的缺点有哪些&#x…...

服务器硬件基础知识

1. 服务器分类 服务器分类 服务器的分类没有一个统一的标准。 从多个多个维度来看服务器的分类可以加深我们对各种服务器的认识。 N.B. CISC: complex instruction set computing 复杂指令集计算 RISC: reduced instruction set computer 精简指令集计算 EPIC: explicitly p…...

matlab实现层次聚类与k-均值聚类算法

1. 原理 1.层次聚类&#xff1a;通过计算两类数据点间的相似性&#xff0c;对所有数据点中最为相似的两个数据点进行组合&#xff0c;并反复迭代这一过程并生成聚类树 2.k-means聚类&#xff1a;在数据集中根据一定策略选择K个点作为每个簇的初始中心&#xff0c;然后将数据划…...

【机器学习】包裹式特征选择之递归特征消除法

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…...

【ArcGIS】重采样栅格像元匹配问题:不同空间分辨率栅格数据统一

重采样栅格像元匹配问题&#xff1a;不同空间分辨率栅格数据统一 原始数据数据1&#xff1a;GDP分布数据2.1&#xff1a;人口密度数据2.2&#xff1a;人口总数数据3&#xff1a;土地利用类型 数据处理操作1&#xff1a;将人口密度数据投影至GDP数据&#xff08;栅格数据的投影变…...

Qt 简约又简单的加载动画 第七季 音量柱风格

今天和大家分享两个音量柱风格的加载动画,这次的加载动画的最大特点就是简单,只有几行代码. 效果如下: 一共三个文件,可以直接编译运行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <QGridLayout> int main(int argc…...

【JS】数值精度缺失问题解决方案

方法一&#xff1a; 保留字符串类型&#xff0c;传给后端 方法二&#xff1a; 如果涉及到计算&#xff0c;用以下方法 // 核心思想 在计算前&#xff0c;将数字乘以相同倍数&#xff0c;让他没有小数位&#xff0c;然后再进行计算&#xff0c;然后再除以相同的倍数&#xff0…...

c++基础知识补充4

单独使用词汇 using std::cout; 隐式类型转换型初始化&#xff1a;如A a1,,此时可以形象地理解为int i1;double ji;&#xff0c;此时1可以认为创建了一个值为1的临时对象&#xff0c;然后对目标对象进行赋值&#xff0c;当对象为多参数时&#xff0c;使用&#xff08;1&#xf…...

leetcode230. 二叉搜索树中第K小的元素

lletcode 230. 二叉搜索树中第K小的元素&#xff0c;链接&#xff1a;https://leetcode.cn/problems/kth-smallest-element-in-a-bst 题目描述 给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 个最小元素&#xff08;从 …...

医学大数据|文献阅读|有关“肠癌+机器学习”的研究记录

目录 1.机器学习算法识别结直肠癌中的免疫相关lncRNA signature 2.基于机器学习的糖酵解相关分子分类揭示了结直肠癌癌症患者预后、TME和免疫疗法的差异&#xff0c;2区7 3.整合深度学习-病理组学、放射组学和免疫评分预测结直肠癌肺转移患者术后结局 4.最新7.4分纯生信&am…...

Linux信号【systemV】

目录 前言 正文&#xff1a; 1消息队列 1.1什么是消息队列&#xff1f; 1.2消息队列的数据结构 1.3消息队列的相关接口 1.3.1创建 1.3.2释放 1.3.3发送 1.3.4接收 1.4消息队列补充 2.信号量 2.1什么是信号量 2.2互斥相关概念 2.3信号量的数据结构 2.4…...

node.js最准确历史版本下载

先进入官网:Node.js https://nodejs.org/en 嫌其他博客多可以到/release下载:Node.js,在blog后面加/release https://nodejs.org/en/blog/release/ 点击next翻页,同样的道理...

UE5 C++ 单播 多播代理 动态多播代理

一. 代理机制&#xff0c;代理也叫做委托&#xff0c;其作用就是提供一种消息机制。 发送方 &#xff0c;接收方 分别叫做 触发点和执行点。就是软件中的观察者模式的原理。 创建一个C Actor作为练习 二.单播代理 创建一个C Actor MyDeligateActor作为练习 在MyDeligateAc…...

前端学习、CSS

CSS可以嵌入到HTML中使用。 每个CSS语法包含两部分&#xff0c;选择器和应用的属性。 div用来声明针对页面上的哪些元素生效。 具体设置的属性以键值对形式表示&#xff0c;属性都在{}里&#xff0c;属性之间用;分割&#xff0c;键和值之间用:分割。 因为CSS的特殊命名风格…...

Flink基本原理 + WebUI说明 + 常见问题分析

Flink 概述 Flink 是一个用于进行大规模数据处理的开源框架&#xff0c;它提供了一个流式的数据处理 API&#xff0c;支持多种编程语言和运行时环境。Flink 的核心优点包括&#xff1a; 低延迟&#xff1a;Flink 可以在毫秒级的时间内处理数据&#xff0c;提供了低延迟的数据…...

3. 文档概述(Documentation Overview)

3. 文档概述&#xff08;Documentation Overview&#xff09; 本章节简要介绍一下Spring Boot参考文档。它包含本文档其它部分的链接。 本文档的最新版本可在 docs.spring.io/spring-boot/docs/current/reference/ 上获取。 3.1 第一步&#xff08;First Steps&#xff09; …...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...