如何在QtWebKit中拦截AJAX-Requests?

Sen*_*nči 6 c++ qt qt4 qtwebkit phantomjs

我想根据SSL证书的指纹拦截,检查和(如果需要)拒绝AJAX请求.我使用该QNetworkAccessManager::createRequest(...)函数发出请求.我使用时一切正常QWebFrame::load(...).甚至在请求中加载的内容(如.css或.js文件)也会发出信号.不幸的是,没有AJAX-Requests会发出任何信号.我知道信号在功能中连接到相同的插槽(用于"普通"和AJAX请求)MyNetworkAccessManager::createRequest(...).

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()));
Run Code Online (Sandbox Code Playgroud)

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

Cam*_*ker 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'); });");
Run Code Online (Sandbox Code Playgroud)

然后你可以在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;
}
Run Code Online (Sandbox Code Playgroud)

我注意到,当您使用 QNetworkReply 执行任何操作时,jQuery AJAX 的完成承诺似乎没有执行,但您可以看到请求实际上在调试控制台中完成。

请参阅我的 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;
}
Run Code Online (Sandbox Code Playgroud)