【QT 网络云盘客户端】——登录界面功能的实现

news2024/11/16 0:26:22

目录

1.注册账号

2.服务器ip地址和端口号设置

3. 登录功能

4.读取配置文件

5.显示主界面


1.注册账号

1.点击注册页面,将数据 输入 到 用户名,昵称,密码,确认密码,手机,邮箱 的输入框中,

点击确定,触发槽函数 on_reg_but_clicked。

2.on_reg_but_clicked 会校验 各个输入框中数据格式 的合法性,比如说手机号只能由数字组成。

使用正则表达式进行检验

3.如果数据没问题,则客户端发送一个http请求给服务器:

POST http://119.23.41.13:80/register HTTP/1.1
Content-Type: application/json

{
    "email": "sjp3250506022@qq.com",  //邮箱
    "firstPwd": "e10adc3949ba59abbe56e057f20f883e",//密码,用md5值进行加密
    "nickName": "lisi", //昵称
    "phone": "13727989171", //电话号码
    "userName": "lisi"  //用户名
}

服务器响应:


"code":	"002" //账号注册成功
"code":	"003" //用户已经存在
"code":	"004" //账号注册失败

 实现:

//注册框的流程
void Dialog::on_reg_but_clicked()
{
        /*
          1.获取输入框中的数据
          2.校验数据格式是否正确
          3.封装http请求,发送http请求
          4.接收http响应,处理http响应
        */
        QString usr=ui->usr_edit->text();
        QString nickname=ui->nickname_edit->text();
        QString password=ui->pasword_edit2->text();
        QString confirmpassword=ui->confirm_edit->text();
        QString mail=ui->mailbox_edit->text();
        QString phone=ui->phone_edit->text();
        QRegExp reg(USER_REG);

        //校验账号的规则
        if(!reg.exactMatch(usr))
        {
            //校验失败
            QMessageBox::warning(this,"警告","输入的账号格式有误");
            return;
        }

        reg.setPattern(PASSWD_REG);
        if(!reg.exactMatch(password)){
            QMessageBox::warning(this,"警告","输入的密码格式有误");
            return;
        }

        reg.setPattern(EMAIL_REG);
        if(!reg.exactMatch(mail)){
            QMessageBox::warning(this,"警告","输入的邮箱格式有误");
            return;
        }

        reg.setPattern(PHONE_REG);
        if(!reg.exactMatch(phone)){
            QMessageBox::warning(this,"警告","输入的手机号码格式有误");
            return;
        }

        if(confirmpassword!=password){
            QMessageBox::warning(this,"警告","确认密码不匹配");
            return;
        }

        //
        QNetworkAccessManager* manger=new QNetworkAccessManager();
        //封装http请求
        QNetworkRequest request;
        //从配置文件中获取到ip地址和port端口号
        QString ip=Common::getInstant()->getConfValue("web_server","ip");
        QString port=Common::getInstant()->getConfValue("web_server","port");
        QString url=QString("http://%1:%2/register").arg(ip).arg(port);
        request.setUrl(QUrl(url));
       //设置文件类型
        request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
        //将data数据以QJson的格式发送给服务器

        QJsonObject object;
        object.insert("email", mail);//邮箱
        object.insert("userName", usr);//账号
        object.insert("phone", phone);
        object.insert("nickName", nickname);
        object.insert("firstPwd", m_common->getStrMd5(password));
        QJsonDocument doc(object);

        QByteArray data=doc.toJson();
        //发送数据
        QNetworkReply* rely=manger->post(request,data);
        connect(rely,&QNetworkReply::readyRead,this,[=]{
            //响应到达,读取所有的数据
            QByteArray s=rely->readAll();
             qDebug() << "服务器返回数据:" << QString(s);
             //将s数据转换为Json对象
              QJsonParseError err;
             QJsonDocument document=QJsonDocument::fromJson(s,&err);

            if(err.error!=QJsonParseError::NoError){
                qDebug()<<"QJson格式错误";
                return;
            }
            //将QJson字符串转换为QJson对象
            QJsonObject object1;
            object1=document.object();

            //获取状态码
            QString value1=object1["code"].toString();
            if(value1=="002"){
                QMessageBox::information(this,"提示","账号注册成功");
            }

            if(value1=="003"){
                QMessageBox::warning(this,"警告","该账号已经存在");
            }

            if(value1=="004"){
                QMessageBox::critical(this,"注册失败","注册失败");
            }
             rely->deleteLater();
       });
}

2.服务器ip地址和端口号设置

 

1.点击 确定 按钮,获取服务器 ip 和端口号的 信息

2.验证服务器 和 端口号的格式,如果验证成功,将 服务器的 ip地址和 端口号写入到 cfg.json 配置文件中。

 

 //点击服务器设置页的按钮,将ip地址和端口写入到配置文件中
void Dialog::on_ok_button_clicked()
{
    QString ip=ui->ip_edit->text();
    QString port=ui->port_eidt->text();
    QRegExp reg(IP_REG);
    //校验账号的规则
    if(!reg.exactMatch(ip))
    {
        //校验失败
        QMessageBox::warning(this,"警告","输入的IP地址有误");
        return;
    }

     reg.setPattern(PORT_REG);
    //校验账号的规则
    if(!reg.exactMatch(port))
    {
        //校验失败
        QMessageBox::warning(this,"警告","输入的端口号有误");
        return;
    }

    m_common->writeWebInfo(ip,port);
    QMessageBox::warning(this,"提示","配置成功");
    ui->stackedWidget->setCurrentWidget(ui->login_page);
    return;
}


// 将服务器的ip和port写入到配置文件
void Common::writeWebInfo(QString ip, QString port, QString path)
{

    QMap<QString,QVariant> web_server;
    web_server.insert("ip",ip);
    web_server.insert("port",port);

    QString usr_base64=getConfValue("login","user");
    QString pwd_base64=getConfValue("login","pwd");
    QString remember=getConfValue("login","remember");

    QMap<QString,QVariant> login;
    login.insert("user",usr_base64);
    login.insert("pwd",pwd_base64);
    login.insert("remember",remember);

    QMap<QString, QVariant> json;
    json.insert("web_server", web_server);
    json.insert("login", login);

    QJsonDocument jsonDocument = QJsonDocument::fromVariant(json);
    if ( jsonDocument.isNull() == true)
    {
        qDebug() << "QJsonDocument::fromVariant错误";
        return;
    }

    QFile file(CONF_FILE);
    if(!file.open(QFile::WriteOnly)!=0)
    {
            qDebug()<<"打开文件失败";
            return;
    }

    file.write(jsonDocument.toJson());
    file.close();

    qDebug()<<"配置成功";
}

 

3. 登录功能

 1.点击登录,获取用户名和密码

2.验证 用户名 和密码 格式的 合法性,如果 合法,则发送一个http请求给服务器:

POST http://119.23.41.13:80/login HTTP/1.1
Content-Type: application/json

{
    "pwd": "e10adc3949ba59abbe56e057f20f883e", //密码,用md5进行加密
    "user": "zhangsan"                         //用户名
}

http响应:

//登录成功的响应
HTTP/1.1 200 OK

{
	"code":	"000",
	"token":	"86569b8a537abf45acbb811f0244a69e"
}

//登录失败的响应
HTTP/1.1 200 OK

{
	"code":	"001",
}

登录成功后:

1.客户端需要保存token,因为客户端接下来访问服务器 都需要 加上token来验证身份

2.创建一个 logininfoinstance 实例对象,将 用户名token,服务器ip端口号保存到logininfoinstance方便后续进行读取

3..需要 将用户的 用户名 和密码 写入到 cfg.json文件 中。为了防止泄密,需要对用户名和密码进行二次加密,先进行desc加密,然后再进行base64加密 

4.创建主界面,显示主界面 

代码实现: 

//登录按钮
void Dialog::on_login_toolButton_clicked()
{
    qDebug()<<"登录";
    //获取账号密码
    QString account=ui->account_edit->text();
    QString password=ui->password_edit->text();

    //
    QRegExp reg(USER_REG);

    //校验账号的规则
    if(!reg.exactMatch(account))
    {
        //校验失败
        QMessageBox::warning(this,"警告","输入的账号格式有误");
        return;
    }

    reg.setPattern(PASSWD_REG);

    if(!reg.exactMatch(password)){
        QMessageBox::warning(this,"警告","输入的密码格式有误");
        return;
    }

    //封装http请求
    QNetworkRequest request;
    //从配置文件中获取到ip地址和port端口号

    QString ip=Common::getInstant()->getConfValue("web_server","ip");
    QString port=Common::getInstant()->getConfValue("web_server","port");
    QString url=QString("http://%1:%2/login").arg(ip).arg(port);//设置登录的url
    request.setUrl(QUrl(url));

    //设置文件类型
    request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
    //将data数据以QJson的格式发送给服务器

    QJsonObject object;
    object.insert("user", account);
    object.insert("pwd",  m_common->getStrMd5(password));

    QJsonDocument doc(object);
    QByteArray data=doc.toJson();
    //发送数据
    QNetworkReply* rely=manger->post(request,data);
    connect(rely,&QNetworkReply::readyRead,this,[=]{
        //响应到达,读取所有的数据
        QByteArray s=rely->readAll();
         qDebug() << "服务器返回数据:" << QString(s);
         //将s数据转换为Json对象
         QJsonParseError err;
         QJsonDocument document=QJsonDocument::fromJson(s,&err);

        if(err.error!=QJsonParseError::NoError){
            qDebug()<<"QJson格式错误";
            return;
        }
        //将QJson字符串转换为QJson对象
        QJsonObject object1;
        object1=document.object();

        //获取状态码
        QString value1=object1["code"].toString();
        if(value1=="000"){

            //登录成功
            //0.获取token,将用户信息写入到logininstant中。
            //1.判断有没有记住密码,如果有记住密码,获取记住密码的状态
            //2.将账号和密码信息记录到配置文件中
            //3.显示登录成功页面(主页面)

             //获取token
            QString token=object1["token"].toString();
                qDebug()<<"token:"<<token;
            //获取token,将用户信息写入到logininstant中。
            saveLoginInfoData(account,token,ip,port);


            // QMessageBox::information(this,"登录成功","账号登录成功");
            //判断有没有记住密码
            bool checkBox=ui->rember_checkBox->isChecked();
            if(checkBox==false)
            {
                //没有记住密码直接清除密码框
                ui->password_edit->clear();
            }

            //将账号密码保存到配置文件中
            m_common->writeLoginInfo(account,password,checkBox);
            //获取

           showMainWindow(account);
        }

        if(value1=="001"){
            QMessageBox::warning(this,"警告","登录");
        }
    });
}

​
//common.h文件:
//将用户信息 写入到配置文件
void writeLoginInfo(QString user, QString pwd, bool isRemeber, QString path=CONF_FILE);

// 服务器信息写入到配置文件
void writeWebInfo(QString ip, QString port, QString path=CONF_FILE);

​相关接口(接口实现自行跳转项目链接去查看) 

4.读取配置文件

  1. 当登录界面创建的时候,程序会先去读取conf.json文件内容.将账号密码服务器ip端口号写入到登录界面中。
  2. 由于账号密码在写入配置文件是加密的,读取账号和密码需要 先后进行 base64解密 desc解密,才显示到登录界面。
  3. desc加解密,需要在项目中添加des.c文件和des.h文件
//读取配置文件信息,将账号密码,服务器端口号写到界面中
 void Dialog::readConf()
 {
     QString user_base64=m_common->getConfValue("login","user");
     QString pwd_base64=m_common->getConfValue("login","pwd");
     QString remember=m_common->getConfValue("login","remember");

     //对账号进行base64解密和desc解密
     QByteArray usr_des=QByteArray::fromBase64(user_base64.toLocal8Bit());
     unsigned char usr[1024]={0};
     int usr_len;
     //进行desc解密
     if(DesDec((unsigned char*)usr_des.data(),usr_des.length(),usr,&usr_len)!=0){
         qDebug()<<"desc解密失败";
     }

     //账号解密成功,将账号显示到登录窗口
     QString s=QString::fromLocal8Bit((const char*)usr,usr_len);
     ui->account_edit->setText(s);

     if(remember=="yes")
     {
         ui->rember_checkBox->setCheckState(Qt::Checked);
         //记住密码,将密码显示到密码框上
         QByteArray pwd_des=QByteArray::fromBase64(pwd_base64.toLocal8Bit());
         unsigned char pwd[1024]={0};
         int pwd_len=0;
         //进行desc解密
         if(DesDec((unsigned char*)pwd_des.data(),pwd_des.length(),pwd,&pwd_len)!=0){
             qDebug()<<"密码解密失败";
         }

         //账号解密成功,将账号显示到登录窗口
         QString s1=QString::fromLocal8Bit((const char*)pwd,pwd_len);
         ui->password_edit->setText(s1);
     }


    //将ip地址和端口号显示到服务器设置页面
     QString ip=m_common->getConfValue("web_server","ip");
     QString port=m_common->getConfValue("web_server","port");

     ui->ip_edit->setText(ip);
     ui->port_eidt->setText(port);
 }

5.显示主界面

登录成功,显示主页面:

 


//创建主界面,并显示主界面
void Dialog::showMainWindow(QString account)
{
    //获取主页面
    mainwindow=MainWindow::getinstant();
    mainwindow->setUser(account);//将用户名显示到主页面上
    mainwindow->show();//显示主页面
    this->hide();//隐藏主页面
   
    connect(mainwindow,&MainWindow::switchUser,this,[=](){
        mainwindow->hide();
        this->show();
    });
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3 导出word

&#x1f642;博主&#xff1a;锅盖哒 &#x1f642;文章核心&#xff1a;导出word 目录 1.首先&#xff0c;你需要安装docxtemplater库。可以使用npm或yarn来安装&#xff1a; 2.在Vue组件中&#xff0c;你可以使用docxtemplater来生成Word文档并提供一个导出按钮供用户下载…

线性表之顺序表

在计算机科学中&#xff0c;数据结构是非常重要的基础知识之一。数据结构为我们提供了组织和管理数据的方法和技巧&#xff0c;使得我们可以高效地存储、检索和操作数据。而顺序表作为数据结构中最基本、最常用的一种存储结构&#xff0c;也是我们学习数据结构的第一步。 本文将…

idea 关于高亮显示与选中字符串相同的内容

dea 关于高亮显示与选中字符串相同的内容&#xff0c;本文作为个人备忘的同时也希望可以作为大家的参考。 依次修改File-settings-Editor-Color Scheme-General菜单下的Code-Identifier under caret和Identifier under caret(write)的Backgroud色值&#xff0c;可以参考下图。…

阿里云域名备案

最好的爱情&#xff0c;不是因为我们彼此需要在一起&#xff0c;而是因为我们彼此想要在一起。 阿里云的域名如何备案&#xff0c;域名备案和ICP备案一样吗&#xff1f;&#xff1f; 截至我所掌握的知识&#xff08;2021年9月&#xff09;&#xff0c;阿里云的域名备案和ICP备案…

【GoLang】基础语法(上)

Go基础语法(上) 文章目录 Go基础语法(上)01注释02变量定义初始化打印内存地址变量交换匿名变量变量的作用域 03常量iota 04基本数据类型布尔类型数字类型整型浮点型 字符与字符串 05数据类型转换06运算符算术运算符关系运算符逻辑运算符位运算符赋值运算符 07获取键盘输入 01注…

Java 设计模式 - 简单工厂模式 - 创建对象的简便之道

简单工厂模式是一种创建型设计模式&#xff0c;它提供了一种简单的方式来创建对象&#xff0c;而无需暴露对象创建的逻辑。在本篇博客中&#xff0c;我们将深入了解简单工厂模式的概念、实现方式以及如何在Java中使用它来创建对象。 为什么使用简单工厂模式&#xff1f; 在软…

PC音频框架学习

1.整体链路 下行播放&#xff1a; App下发音源→CPU Audio Engine 信号处理→DSP数字信号处理→Codec DAC→PA→SPK 上行录音&#xff1a; MIC拾音→集成运放→Codec ADC→DSP数字信号处理→CPU Audio Engine 信号处理→App 2.硬件 CPU PCH DSP(可选) Codec PA SPKbox MIC…

Vue 3 中的插槽(Slots)用法

插槽&#xff08;Slots&#xff09;是 Vue 组件中一种非常有用的功能&#xff0c;用于在父组件中向子组件传递内容。Vue 3 引入了 <script setup> 语法&#xff0c;使得组件的写法更加简洁和易读。在本篇博客中&#xff0c;我们将探讨在 Vue 3 中使用插槽的不同方式&…

数据结构与算法基础-学习-27-图之最短路径之Dijkstra(迪杰斯特拉)算法

一、最短路径应用案例 例如从北京到上海旅游&#xff0c;有多条路可以到目的地&#xff0c;哪条路线最短&#xff0c;哪条路线最省钱&#xff0c;就是典型的最短路径问题。 二、最短路径问题分类 最短路径问题可以分为两类&#xff0c;第一类为&#xff1a;两点间最短路径。第…

函数栈帧的创建和毁销【C语言版】

大家好&#xff0c;我是深鱼~ 【前言】前期学习的时候&#xff0c;我们可能有很多的困惑 比如&#xff1a; 局部变量是怎么创建的呢&#xff1f; 为什么局部变量的值是随机值&#xff1f; 函数是怎么传参的&#xff1f;传参的顺序是怎么样的&#xff1f; 形参和实参是什么关系…

上海亚商投顾:沪指放量大涨1.84% 证券股掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 三大指数今日低开高走&#xff0c;沪指午后放量涨近2%&#xff0c;上证50盘中大涨超3%。大金融板块全线爆发&#…

Wireshark从下载到使用完整教程分享

surfshark如何下载呢&#xff1f;surfshark安卓&#xff0c;苹果以及电脑上使用的完整教程分享可以戳后面地址: https://qptool.net/shark.html Wireshark是一款流行的网络协议分析工具&#xff0c;用于捕获和分析网络数据包。它可以帮助网络管理员和安全专家监视和诊断网络问…

[每日习题]跳石板(动态规划) 手套(贪心)——牛客习题

hello,大家好&#xff0c;这里是bang___bang_&#xff0c;今天来记录2道习题跳石板和手套&#xff01; 目录 1️⃣跳石板 2️⃣手套 1️⃣跳石板 跳石板_牛客题霸_牛客网 (nowcoder.com) 描述 小易来到了一条石板路前&#xff0c;每块石板上从1挨着编号为&#xff1a;1、2、…

批量删除python代码中的注释

ctrlh&#xff0c;调出替换功能窗口 启用正则表达式&#xff0c;输入 (#.*) 点击替换就能删除全部的注释了

【图论】LCA(倍增)

一.LCA介绍 LCA通常指的是“最近共同祖先”&#xff08;Lowest Common Ancestor&#xff09;。LCA是一种用于解决树或图结构中两个节点的最低共同祖先的问题的算法。 在树结构中&#xff0c;LCA是指两个节点的最近层级的共同祖先节点。例如&#xff0c;考虑一棵树&#xff0c;…

16.Netty源码之ChannelPipeline

highlight: arduino-light 服务编排层:ChannelPipeline协调ChannelHandlerHandler EventLoop可以说是 Netty 的调度中心&#xff0c;负责监听多种事件类型&#xff1a;I/O 事件、信号事件、定时事件等&#xff0c;然而实际的业务处理逻辑则是由 ChannelPipeline 中所定义的 Cha…

《Elasticsearch 源码解析与优化实战》第5章:选主流程

《Elasticsearch 源码解析与优化实战》第5章&#xff1a;选主流程 - 墨天轮 一、简介 Discovery 模块负责发现集群中的节点&#xff0c;以及选择主节点。ES 支持多种不同 Discovery 类型选择&#xff0c;内置的实现称为Zen Discovery ,其他的包括公有云平台亚马逊的EC2、谷歌…

C++之普通函数指针/类成员函数指针/lambda回调函数总结(一百六十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

边写代码边学习之卷积神经网络CNN

1. 卷积神经网络CNN 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;是一种深度学习神经网络的架构&#xff0c;主要用于图像识别、图像分类和计算机视觉等任务。它是由多层神经元组成的神经网络&#xff0c;其中包含卷积层、池化层和全连接…

算法与数据结构-二分查找

文章目录 什么是二分查找二分查找的时间复杂度二分查找的代码实现简单实现&#xff1a;不重复有序数组查找目标值变体实现&#xff1a;查找第一个值等于给定值的元素变体实现&#xff1a;查找最后一个值等于给定值的元素变体实现&#xff1a;查找最后一个小于给定值的元素变体实…