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¶m%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();//忽略关闭事件
}
json解析来自于github,虽然qt也有json解析,但是哪有我直接从以前工程复制代码来得爽快。
也许还有完善的地方吧,反正先用用再说了。
简直是离谱,家里写的源代码加上innosetup的压缩包,竟然也能检测出病毒来。
真是呵呵了。
测试一下,登录成功了。也能上网了,那就是能用。
源代码下载