Qt写一个惠尔顿网络自动登录程序

QT做一个惠尔顿自动登录程序。

出于某种要求,公司使用了这个惠尔顿网络安全审计系统。

关键是这个做得不太行吧,提供的GUI程序,又大又难用(搞不懂,简单的东西做这么复杂)。

还提供了网页登录程序,这个就简单,只需要输入账号密码点击登录即可。

但是吧,他喵的,必须保持登录页面打开,也就是一直占用那个浏览器的一个标签页。

这他喵的也很恶心了,尤其是针对浏览器使用和切换都很频繁的人来说。

是可忍,孰不可忍。使用fidlder一抓包,一Compaser post一下,就发现了登录的网页,以及参数。

POST http://192.168.0.98/user-login-auth HTTP/1.1
Host: 192.168.0.98
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

param%5BUserName%5D=username&param%5BUserPswd%5D=123456


网页版确实简单,可以精简到简单的post账号和密码就能验证通过,当然,需要对一些字符进行url编码

没什么好分析的,谈需求。

1.越简单越好,我们只想使用这软件一次,以后再也不用自己输出账号密码,然后点击登录。
那就需要读写文件,保存账号密码。//简单起见,自己构造个json文件即可
那就需要开机自动运行。//注册表操作
2.虽然我没遇见过,但是他们反映使用过程中,虽然登录成功,但是后面还是断网了。也就是连接可能不稳定。
那就需要不停的检测网络连接,断网就需要自己post登录。
3.虽然直接打包成压缩文件也能用,但是使用的对象不全是程序员,要是随便的移动软件,岂不是多了很多注册表垃圾。
那就弄成安装包吧。

主体代码如下:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QDebug>
#include <QNetworkRequest>
#include <QMessageBox>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QFile>
#include <iostream>
#include <QCloseEvent>
#include <QTimer>
//#define DEBUG
#define QS(x) QString::fromUtf8(x)
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    bool checkFile();
    void autoLogin(QString un,QString ps);
    void CreateSystemTrayIcon();
private slots:
    void on_pushButton_clicked();
    void requestFinished(QNetworkReply*);

    void on_lineEdit_2_returnPressed();

private:
    Ui::Widget *ui;
    QString success;
    QString fail;
    QString username = "";
    QString password = "";
    QTimer time;
#ifdef DEBUG
    const QString LOGIN = "http://192.168.0.102:90/test.html";
#else
    const QString LOGIN="http://192.168.0.98/user-login-auth";
#endif
protected:
    void closeEvent(QCloseEvent *event);//由于要关闭窗口变为隐藏至托盘图标,所以要重写close事件

};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"
#include "jsonxx.h"
#include "jsonxx.cc"
#include <qnetworkproxy.h>
#include <QTextCodec>
#include <QMenu>
#include <QSystemTrayIcon>
#include <QAction>
#include <QSettings>
using namespace std;
using namespace jsonxx;
#define AUTO_RUN_KEY	"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
//#define DEBUG
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    success = "color:green";
    fail = "color:red";
    time.setInterval(30000);//30s自动登录一次
    QObject::connect(&time, &QTimer::timeout, [=]()
    {
        autoLogin(username,password);
    });
    if(checkFile())
    {
        //隐藏到托盘
        CreateSystemTrayIcon();
    }
}

Widget::~Widget()
{
    delete ui;
}

//读取配置文件
bool Widget::checkFile()
{

    QFile file("config.txt");
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
    {
        qDebug()<<file.errorString();
        return false;
    }
    else
    {
        qDebug()<<"openok";
    }
    QByteArray tt = file.read(1024);
    QString tta;
    tta = tta.fromLocal8Bit(tt);
    string str = tta.toStdString();
    Object o;
    if(o.parse(str))
    {
        QString username = "";
        QString password = "";
        QString tmp = "";
        qDebug()<<"success to parse";
        if(!o.has<String>("un"))
        {
            return false;
        }
        str = o.get<String>("un");
        username = QString::fromStdString(str);
        ui->lineEdit->setText(username);
        if(!o.has<String>("ps"))
        {
            return false;
        }
        str = o.get<String>("ps");
        password = QString::fromStdString(str);
        ui->lineEdit_2->setText(password);
        if(!o.has<String>("autoLogin"))
        {
            qDebug()<<"meiyou";
            return false;
        }
        str = o.get<String>("autoLogin");
        tmp = QString::fromStdString(str);
        if("true"!=tmp){
            return false;
        }
        ui->checkBox->setCheckState(Qt::Checked);
        autoLogin(username,password);
    }else{
        return false;
    }
}

void Widget::autoLogin(QString un, QString ps)
{
    QNetworkRequest request;
    QNetworkAccessManager* naManager = new QNetworkAccessManager(this);
    QMetaObject::Connection connRet = QObject::connect(naManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
    Q_ASSERT(connRet);
    request.setUrl(QUrl(LOGIN));
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
    QByteArray postData;
#ifdef DEBUG
    QNetworkProxy proxy;
    proxy.setHostName("127.0.0.1");
    proxy.setPort(8888);
    naManager->setProxy(proxy);
#endif
    QString s = QUrl::toPercentEncoding("param[UserName]") + "=" + QUrl::toPercentEncoding(un) + "&" + QUrl::toPercentEncoding("param[UserPswd]") + "=" + QUrl::toPercentEncoding(ps);
    postData.append(s);
    qDebug()<<s<<endl;
    naManager->post(request,postData);
    username = un;
    password = ps;
}

void Widget::CreateSystemTrayIcon()
{
    QAction* show = new QAction(QS("打开界面"));
    QAction* login = new QAction(QS("登录"));
    QAction* quit = new QAction(QS("退出"));

    connect(show, &QAction::triggered, this, [=]()
    {
        this->showNormal();
    });
    connect(login, &QAction::triggered, this, [=]()
    {
        if(!username.isEmpty()&&!password.isEmpty())
        {
            this->autoLogin(username,password);
        }
        else
        {
            on_pushButton_clicked();
        }
    });
    connect(quit , &QAction::triggered, this, [=]()
    {
        qDebug()<<"exit";
        QApplication::exit(0);
    });

    QMenu* trayMenu = new QMenu(this);//菜单
    trayMenu->addAction(show);
    trayMenu->addAction(login);
    trayMenu->addAction(quit);

    //创建一个系统托盘
    QSystemTrayIcon* trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(QPixmap(":/photo/pic.ico")));
    trayIcon->setContextMenu(trayMenu);//设置菜单
    trayIcon->show();
    connect(trayIcon, &QSystemTrayIcon::activated, this, [=](QSystemTrayIcon::ActivationReason reason)
    {
        qDebug()<<reason;
        qDebug()<<QApplication::mouseButtons();
        if(reason == QSystemTrayIcon::Trigger&&QApplication::mouseButtons()==Qt::LeftButton)
        {
            this->showNormal();
        }
        else
        {
            qDebug()<<"没到条件";
        }
    });

}

void Widget::requestFinished(QNetworkReply * reply)
{
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if(statusCode.isValid())
    {
        qDebug() << "status code=" << statusCode.toInt();
    }

    QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
    if(reason.isValid())
    {
        qDebug() << "reason=" << reason.toString();
#ifdef DEBUG
        if(reason.toString().contains("allowed",Qt::CaseInsensitive))
        {
            qDebug()<<"success";
            ui->label_3->setStyleSheet(success);
            ui->label_3->setText(QS("登录成功"));
            time.start();
        }
        else
        {
            qDebug()<<"fail";
            ui->label_3->setStyleSheet(fail);
            ui->label_3->setText(QS("登录失败"));
            time.stop();
            username = "";
            password = "";
            this->showNormal();
        }
#endif
    }

    QNetworkReply::NetworkError err = reply->error();
    if(err != QNetworkReply::NoError) {
        qDebug() << "Failed: " << reply->errorString();//弹出警告框
        ui->label_3->setStyleSheet(fail);
        ui->label_3->setText(QS("登录失败"));
        username = "";
        password = "";
        time.stop();
        this->showNormal();
        return;
    }
    else {
        QString s = reply->readAll();
        if(s.contains("success",Qt::CaseInsensitive))//不区分大小写
        {
            ui->label_3->setStyleSheet(success);
            ui->label_3->setText(QS("登录成功"));
            time.start();
        }
        else
        {
            ui->label_3->setStyleSheet(fail);
            ui->label_3->setText(QS("登录失败"));
            username = "";
            password = "";
            time.stop();
            this->showNormal();
        }
    }
}


void Widget::on_pushButton_clicked()
{
    bool check = ui->checkBox->checkState();
    QString username = ui->lineEdit->text();
    QString password = ui->lineEdit_2->text();
    if(username.isEmpty())
    {
        QMessageBox::information(NULL,QS("提示"),QS("请输入账号"),QMessageBox::Ok);
        return;
    }
    if(password.isEmpty())
    {
        QMessageBox::information(NULL,QS("提示"),QS("请输入账号"),QMessageBox::Ok);
        return;
    }
    qDebug()<<username<<endl;
    qDebug()<<password<<endl;
    if(check)
    {
        QString str = "";
        str = "{'un':'"+username+"','ps':'"+password+"','autoLogin':'true'}";
        QFile file("config.txt");
        if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            return;
        }
        QByteArray data = str.toLocal8Bit();
        file.write(data);
        qDebug()<<"length = "<<data.length()<<endl;
        file.close();
        QString application_name = QApplication::applicationName();//获取应用名称
        QSettings *settings = new QSettings(AUTO_RUN_KEY, QSettings::NativeFormat);//创建QSetting, 需要添加QSetting头文件
        QString application_path = QApplication::applicationFilePath();//找到应用的目录
        settings->setValue(application_name, application_path.replace("/", "\\"));//写入注册表
    }
    else
    {
        QString str = "";
        str = "{'un':'"+username+"','ps':'"+password+"','autoLogin':'true'}";
        QFile file("config.txt");
        if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            return;
        }
        QByteArray data = str.toLocal8Bit();
        file.write(data);
        qDebug()<<"length = "<<data.length()<<endl;
        file.close();
    }
    autoLogin(username,password);
}

void Widget::on_lineEdit_2_returnPressed()
{
    on_pushButton_clicked();
}

void Widget::closeEvent(QCloseEvent *event)
{
    hide();//隐藏窗口
    event->ignore();//忽略关闭事件
}

C++开发的json解析

json解析来自于github,虽然qt也有json解析,但是哪有我直接从以前工程复制代码来得爽快。

也许还有完善的地方吧,反正先用用再说了。

image

简直是离谱,家里写的源代码加上innosetup的压缩包,竟然也能检测出病毒来。

image

真是呵呵了。
image

测试一下,登录成功了。也能上网了,那就是能用。
源代码下载

posted @ 2022-04-21 23:13  念秋  阅读(531)  评论(0编辑  收藏  举报