如何在QtWebKit中拦截AJAX请求?

6
我希望能够拦截、检查并(如果需要)拒绝基于SSL证书指纹的AJAX请求。我使用QNetworkAccessManager :: createRequest(...)函数来发出请求。当我使用QWebFrame :: load(...)时,一切都正常。甚至请求中加载的内容(如.css或.js文件)也会发出信号。不幸的是,没有任何 AJAX 请求发出任何信号。我知道这些信号与MyNetworkAccessManager::createRequest(...)函数中“普通”和 AJAX 请求所连接的相同槽位相连。
QNetworkReply *reply = QNetworkAccessManager::createRequest(op, req, outgoingData);
connect(reply, SIGNAL(readyRead()), this, SLOT(handleStarted()));
connect(reply, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(handleSslErrors(const QList<QSslError> &)));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleNetworkError()));

为什么AJAX请求如此不同?我在哪里可以访问它们?

所以,您正在尝试显示一个包含一些使用 AJAX 请求其他信息的 JavaScript 代码的页面?这就是您正在做的事情吗? - Mats Petersson
不,我想要访问服务器的SSL证书,以进行SSL指纹匹配。 - Senči
1个回答

2

据我所知,AJAX请求会在QNetworkAccessManager上发出完成信号。您需要连接到QWebPage实例上的QNetworkAccessManager实例:

QWebPage *page = ui->webView->page();
QNetworkAccessManager *nam = page->networkAccessManager();

connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));

QFile file;
file.setFileName(":/js/jquery-2.1.1.min.js"); // jQuery is loaded as a resource
file.open(QIODevice::ReadOnly);
QString jQuery = file.readAll();
file.close();

ui->webView->load(QUrl("about:blank"));
QWebFrame *frame = m_page->mainFrame();


frame->evaluateJavaScript(jQuery); // load jQuery

// check that jQuery is loaded
frame->evaluateJavaScript("$(document).ready(function() { alert('jQuery loaded!'); });");

// do an AJAX GET
frame->evaluateJavaScript("$.ajax({"
                          "url: 'http://www.json-generator.com/api/json/get/cqkXBAEoQy?indent=2',"
                          "method: 'GET',"
                          "dataType: 'json'"
                      "}).done(function (data) {"
                          "for (var i = 0; i < data.length; i++) {"
                              "alert(data[i].name);"
                          "}"
                      "}).error(function (data) { alert('AJAX error'); });");

然后您可以在replyFinished插槽中监视回复,如下所示:
void MainWindow::replyFinished(QNetworkReply *reply)
{
    QByteArray bytes = reply->readAll();
    QString str = QString::fromUtf8(bytes.data(), bytes.size());
    QString replyUrl = reply->url().toString();
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug() << statusCode;
    qDebug() << replyUrl;
    qDebug() << str;
}

我注意到jQuery AJAX的完成承诺(done promise)似乎不会在您对QNetworkReply执行任何操作时执行,但是您可以在调试控制台中看到请求实际上已经完成。
请访问我的GitHub存储库以尝试上述代码:https://github.com/pcmantinker/QtWebkitAJAX 至于基于SSL证书阻止连接,您需要子类化QNetworkAccessManager并覆盖QNetworkAccessManager :: createRequest。以下内容可能有效:
QNetworkReply *CustomQNetworkAccessManager::createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
{
    QNetworkRequest req(request);
    QNetworkReply *reply = QNetworkAccessManager::createRequest(op, req, outgoingData);
    QSslConfiguration *sslConfig = reply->sslConfiguration();
    QList<QSslCertificate> sslCaCerts = sslConfig->caCertificates();
    // do something with sslCaCerts

    return reply;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接