欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

QWebView 拦截http请求,获取post数据

程序员文章站 2022-03-28 11:11:05
...

QWebView作为QT中自带的浏览器控件,使用简单方便,而功能强大。并且很容易通过扩展实现一些定制化需求。

实际业务中遇到一个需求:需要加载某个网页,待用户选择表单选项并提交之后,拦截HTTP请求,获取其Post数据,加以修改 后重新提交请这求。

查阅QT的官方文档,并没有找到相关功能可以实现,而网上这方面的资料也是少之又少,所以特意整理出来方便大家。

注意事项:

QWebView只在QT5.5以下的版本中存在,在QT5.6之上的版本中已经被QWebEngineView取代

另外,QT的MINGW版本中也没有webenginewidgets模块,需要自己编译MSVC版本自带此模块。

示例中使用QT版本号:Qt 5.5.1 (MSVC 2013, 32 bit)

几个主要函数:

1.void QWebPage::setNetworkAccessManager(QNetworkAccessManager * manager)

void QWebPage::setNetworkAccessManager(QNetworkAccessManager * manager)

Sets the QNetworkAccessManager manager responsible for serving network requests for this QWebPage.

Note: It is currently not supported to change the network access manager after the QWebPage has used it. The results of doing this are undefined.

See also networkAccessManager().

通过这个函数将manager设置成我们自己子类化之后的QNetworkAccessManager,方便拦截。

2.virtual QNetworkReply * createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0)

QNetworkReply * QNetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0)

Returns a new QNetworkReply object to handle the operation op and request req. The device outgoingData is always 0 for Get and Head requests, but is the value passed to post() and put() in those operations (the QByteArray variants will pass a QBuffer object).

The default implementation calls QNetworkCookieJar::cookiesForUrl() on the cookie jar set with setCookieJar() to obtain the cookies to be sent to the remote server.

The returned object must be in an open state.

通过重写此子类化函数,我们在自己的子类化的类中既可以获取到我们想要的内容。

此函数的三个参数:

参数1:OPeration op是一个枚举类型,对应定义值如下:

QWebView 拦截http请求,获取post数据

我们想要的post请求对应的op=4.

参数2:QNetWorkRequest& req.请求对象,包含URL,设置的其他head选项。

参数3:QIODevice* outgongingData 。这个参数只有当是post或者put请求时才有内容,其他情况下值为0.



以登陆百度账户为例:

QWebView 拦截http请求,获取post数据

在调试窗口可看到拦截的内容:

QWebView 拦截http请求,获取post数据


代码:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWebView>
#include <QUrl>
#include <QVBoxLayout>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    QWebView* m_pWebView;
    QWidget *centralWidget;
    QVBoxLayout *verticalLayout_2;
    QVBoxLayout *verticalLayout;
    QMenuBar *menuBar;
    QToolBar *mainToolBar;
    QStatusBar *statusBar;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <mnetworkaccessmanager.h>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    m_pWebView = new QWebView(this);
    QNetworkAccessManager *oldManager = m_pWebView->page()->networkAccessManager();
    MNetworkAccessManager *newManager = new MNetworkAccessManager(oldManager, this);
    m_pWebView->page()->setNetworkAccessManager(newManager);
    m_pWebView->page()->setForwardUnsupportedContent(true);
    m_pWebView->load(QUrl("https://www.baidu.com/"));
    this->setCentralWidget(m_pWebView);
}

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

void MainWindow::on_pushButton_clicked()
{

}
#ifndef MNETWORKACCESSMANAGER_H
#define MNETWORKACCESSMANAGER_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QNetworkRequest>
class MNetworkAccessManager : public QNetworkAccessManager
{
    Q_OBJECT

public:
    explicit MNetworkAccessManager(QNetworkAccessManager *manager, QObject *parent);

protected:
    QNetworkReply * createRequest(QNetworkAccessManager::Operation operation,
                                  const QNetworkRequest &request, QIODevice *device);
};

#endif // MNETWORKACCESSMANAGER_H
#include "mnetworkaccessmanager.h"
#include "QDebug"
#include <QBuffer>
MNetworkAccessManager::MNetworkAccessManager(QNetworkAccessManager *manager, QObject *parent)
{
    setCache(manager->cache());
    setCookieJar(manager->cookieJar());
    setProxy(manager->proxy());
    setProxyFactory(manager->proxyFactory());
}

QNetworkReply *MNetworkAccessManager::createRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QIODevice *device)
{
    if(device)
    {
        qDebug()<<(int)operation<<request.url();
        //qDebug()<<device->readAll();
        //这里读取过之后 QIODevice 就不管用了,要重新设置,不然网站接收不到请求
        QByteArray bytes=device->readAll();
        qDebug()<<bytes;
        QBuffer * pDeVice=new QBuffer(this);
        pDeVice->setData(bytes);
        return QNetworkAccessManager::createRequest(operation, request, pDeVice);
    }
    else
    {
        return QNetworkAccessManager::createRequest(operation, request, device);
    }


}

参考:

https://blog.csdn.net/davidsu33/article/details/51058905

完整工程:https://download.csdn.net/download/lacoucou/10440360

相关标签: QWebView post