如何在QtWebKit中拦截AJAX-Requests?

时间:2014-06-11 18:19:42

标签: c++ qt qt4 phantomjs qtwebkit

我想根据SSL证书的指纹拦截,检查和(如果需要)拒绝AJAX请求。我使用QNetworkAccessManager::createRequest(...)函数发出请求。当我使用QWebFrame::load(...)时,一切正常。甚至在请求中加载的内容(如.css或.js文件)也会发出信号。不幸的是,没有AJAX-Requests会发出任何信号。我知道信号在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请求如此不同?我在哪里可以访问它们?

1 个答案:

答案 0 :(得分: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;
}

我注意到当您对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;
}
相关问题