记录登录状态的功能的实现

编程入门 行业动态 更新时间:2024-10-27 21:19:15

记录登录<a href=https://www.elefans.com/category/jswz/34/1771386.html style=状态的功能的实现"/>

记录登录状态的功能的实现

1.Redis相关介绍;

C++连接redis工具:
hiredis安装

cd /home/shiyanlou
wget .14.0.tar.gz
tar -xzf v0.14.0.tar.gz
cd hiredis-0.14.0/
make
sudo make install##复制路径
sudo cp /usr/local/lib/libhiredis.so.0.14 /usr/lib/

测试程序:

#include <iostream>
#include <hiredis/hiredis.h>
using namespace std;
int main(){redisContext *c = redisConnect("127.0.0.1",6379);if(c->err){redisFree(c);cout<<"连接失败"<<endl;return 1;}cout<<"连接成功"<<endl;redisReply *r = (redisReply*)redisCommand(c,"PING");cout<<r->str<<endl;return 0;
}

打开redis:

cd /usr/bin
./redis-server

打开新终端:

g++ -o test_redis test_redis.cpp -lhiredis
./test_redis##运行程序


hiredis常见API

2 服务端

2.1 功能概述:

利用 Redis 记录用户登录状态(HASH 类型,键为 sessionid,值为 session 对象,键五分钟后过期),当用户成功登录时服务器会利用随机算法生成 sessionid 发送到客户端保存,客户登录时会优先发送 sessionid到服务器检查,如果检查通过就不用输入账号密码登录。

2.2头文件添加:

global.h

#ifndef _GLOBAL_H
#define _GLOBAL_H#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <iostream>
#include <thread>
#include <vector>
#include <mysql/mysql.h>
#include <unordered_map>
#include <pthread.h>
#include <set>
#include <hiredis/hiredis.h>    //补充
using namespace std;#endif

2.3HandleRequest代码修改:

  1. redis的连接:
//连接redis数据库
redisContext *redis_target = redisConnect("127.0.0.1",6379);
if(redis_target->err){redisFree(redis_target);cout<<"连接redis失败"<<endl;
}
  1. 查看是否存在session
//先接收cookie看看redis是否保存该用户的登录状态
if(str.find("cookie:")!=str.npos){string cookie=str.substr(7);// 查询该cookie是否存在:hget cookie namestring redis_str="hget "+cookie+" name";redisReply *r = (redisReply*)redisCommand(redis_target,redis_str.c_str());string send_res;//存在if(r->str){cout<<"查询redis结果:"<<r->str<<endl;send_res=r->str;}//不存在elsesend_res="NULL";send(conn,send_res.c_str(),send_res.length()+1,0);
}
  1. 生成sessionId并发送
    生成SessionId算法:10位sessionid,每位由大写字母小写字母以及数字中随机生成;
//登录
else if(str.find("login")!=str.npos){int p1=str.find("login"),p2=str.find("pass:");name=str.substr(p1+5,p2-5);pass=str.substr(p2+5,str.length()-p2-4);string search="SELECT * FROM USER WHERE NAME=\"";search+=name;search+="\";";cout<<"sql语句:"<<search<<endl;auto search_res=mysql_query(con,search.c_str());auto result=mysql_store_result(con);int col=mysql_num_fields(result);//获取列数int row=mysql_num_rows(result);//获取行数//查询到用户名if(search_res==0&&row!=0){cout<<"查询成功\n";auto info=mysql_fetch_row(result);//获取一行的信息cout<<"查询到用户名:"<<info[0]<<" 密码:"<<info[1]<<endl;//密码正确if(info[1]==pass){cout<<"登录密码正确\n\n";string str1="ok";if_login=true;login_name=name;pthread_mutex_lock(&name_sock_mutx); //上锁name_sock_map[login_name]=conn;//记录下名字和文件描述符的对应关系pthread_mutex_unlock(&name_sock_mutx); //解锁// 随机生成sessionid并发送到客户端srand(time(NULL));//初始化随机数种子for(int i=0;i<10;i++){int type=rand()%3;//type为0代表数字,为1代表小写字母,为2代表大写字母if(type==0)str1+='0'+rand()%9;else if(type==1)str1+='a'+rand()%26;else if(type==2)str1+='A'+rand()%26;}//将sessionid存入redisstring redis_str="hset "+str1.substr(2)+" name "+login_name;redisReply *r = (redisReply*)redisCommand(redis_target,redis_str.c_str());//设置生存时间,默认300秒redis_str="expire "+str1.substr(2)+" 300";r=(redisReply*)redisCommand(redis_target,redis_str.c_str());cout<<"随机生成的sessionid为:"<<str1.substr(2)<<endl;send(conn,str1.c_str(),str1.length()+1,0);}//密码错误else{cout<<"登录密码错误\n\n";char str1[100]="wrong";send(conn,str1,strlen(str1),0);}}//没找到用户名else{cout<<"查询失败\n\n";char str1[100]="wrong";send(conn,str1,strlen(str1),0);}
}

3.客户端

3.1 功能概述

大致步骤:在本地创建cookie.txt 文件存储sessionId;
第一次登录,接受sessionid存储至cookie.txt当中;

将其发送至服务端,和redis 中数据进行对比;
由服务端发送结果到客户端;
若对比成功,则直接登录成功;

3.2对比sessionId;

ifstream f("cookie.txt");
string cookie_str;
if(f.good()){f>>cookie_str;f.close();cookie_str="cookie:"+cookie_str;//将cookie发送到服务器send(sock,cookie_str.c_str(),cookie_str.length()+1,0);//接收服务器答复char cookie_ans[100];memset(cookie_ans,0,sizeof(cookie_ans));recv(sock,cookie_ans,sizeof(cookie_ans),0);//判断服务器答复是否通过string ans_str(cookie_ans);if(ans_str!="NULL"){//redis查询到了cookie,通过if_login=true;login_name=ans_str;}

3.3登录新建cookie.txt

 //开始处理注册、登录事件while(1){if(if_login)break;cin>>choice;if(choice==0)break;//注册else if(choice==2){cout<<"注册的用户名:";cin>>name;while(1){cout<<"密码:";cin>>pass;cout<<"确认密码:";cin>>pass1;if(pass==pass1)break;elsecout<<"两次密码不一致!\n\n";}name="name:"+name;pass="pass:"+pass;string str=name+pass;send(conn,str.c_str(),str.length(),0);cout<<"注册成功!\n";cout<<"\n继续输入你要的选项:";}//登录else if(choice==1&&!if_login){while(1){cout<<"用户名:";cin>>name;cout<<"密码:";cin>>pass;string str="login"+name;str+="pass:";str+=pass;send(sock,str.c_str(),str.length(),0);//发送登录信息char buffer[1000];memset(buffer,0,sizeof(buffer));recv(sock,buffer,sizeof(buffer),0);//接收响应string recv_str(buffer);if(recv_str.substr(0,2)=="ok"){if_login=true;login_name=name;string tmpstr=recv_str.substr(2);tmpstr="cat > cookie.txt <<end \n"+tmpstr+"\nend";system(tmpstr.c_str());cout<<"登陆成功\n\n";break;}elsecout<<"密码或用户名错误!\n\n";}       }}//登陆成功while(if_login&&1)```
## 4 功能展示;
服务端
![在这里插入图片描述](.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiJ4oWm,size_20,color_FFFFFF,t_70,g_se,x_16)
客户端:
![在这里插入图片描述](.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiJ4oWm,size_19,color_FFFFFF,t_70,g_se,x_16)

更多推荐

记录登录状态的功能的实现

本文发布于:2023-07-28 19:54:36,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1293532.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:状态   功能

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!