我正在寻找一种方法来访问和篡改 Qt 应用程序发送和接收的原始数据包数据,但找不到任何东西。有什么方法吗?或者如果不是应用程序,至少有一种方法可以从 QWebView 访问数据包数据。
有没有什么方法可以实现以上两种?
在网络连接中篡改发送/接收到服务器的数据的正确方法是使用QNetworkAccessManager
.
此类允许您向服务器发送请求(可能带有标头)并获得响应(也带有标头)。
QNetworkReply
您可以访问在相应对象上接收到的数据。还有响应的标题:
{
...
QNetworkAccessManager *qnam = new QNetworkAccessManager(this);
connect(qnam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
QNetworkRequest request;
request.setUrl(QUrl("http://stackoverflow.com"));
request.setRawHeader("User-Agent", "Foo browser");
qnam->get(QNetworkRequest(request));
...
}
然后定义槽:
void MyWidget::replyFinished(QNetworkReply *reply)
{
QByteArray response = reply->readAll();
QString mime = reply->header(QNetworkRequest::ContentTypeHeader).toString();
...
}
事实上,aQWebView
有一个QNetworkAccessManager
对象来执行请求和管理回复。您可以通过该QWebPage::networkAccessManager()
方法获取该对象。您可以通过 获取QWebPage
来自 aQWebView
的QWebView::page()
。
编辑
要操作显示的网页QWebView
,可以通过 直接设置新的 HTML 内容webView->setHtml(QString html)
。
您还可以通过QWebFrame
类的方法直接访问 HTML。
要获得此类对象,您必须执行以下操作:
QWebFrame *wb = webView->page()->currentFrame();
方法是:
void QWebFrame::setContent ( const QByteArray & data, const QString & mimeType = QString(), const QUrl & baseUrl = QUrl() )
用于在字节数组中设置新文档。
void QWebFrame::setHtml ( const QString & html, const QUrl & baseUrl = QUrl() )
做同样的事情,但考虑到 HTML 文档的内容。
QString QWebFrame::toHtml () const
以 HTML 文档的形式获取内容。
QString QWebFrame::toPlainText () const
同上,纯文本。
查看这些功能的文档。
编辑2:
最后,如果您想访问或过滤QWebView
自己发出的请求,我只能看到一种方法:派生一个类QNetworkAccessManager
并覆盖用于发出请求和接收答案的方法。
然后,将该类的一个实例设置为 QWebView 使用的 QNetworkAccessManager。
让我用骨架澄清一下:
class MyNAM : public QNetworkAccessManager
{
// ...
MyNAM(QObject *parent = 0) : QNetworkAccessManager(parent) { }
// ...
virtual QNetworkReply * createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0) {
// e.g. logging of the request
// e.g. decide if the request must be made
if (some_bool_deciding) {
QNetworkAccessManager::createRequest(op, req, outgoingData);
}
else {
// or faked...
}
// etc.
}
// ...
};
在您的主应用程序中,您必须:
// ...
MyNAM *nam = new MyNAM();
webview->page()->setNetworkAccessManager(nam);
// ...
从现在开始,所有请求都将使用该对象进行。
此方法允许完全控制导航器发出的请求:过滤和访问请求数据(标头、获取和发布值等)。您可以记录请求、分析请求及其 POST/GET 字段等。
希望最终有所帮助!
对不起,山姆,我不能让它工作。我一直在尝试我能想象到的一切,但一切都没有如我所愿。
让我们列出一个简短的选项列表以及可以做什么和不可以做什么:
QWebFrame
您可以通过获取withwebView->page()->currentFrame()
然后访问诸如 、 或 之类的方法setContents()
来访问setHtml()
检索到的网页。您可以通过这些功能动态更改小部件中显示的网页。toHtml()
toPlainText()
reply->readAll()
您可以通过replyFinished()
槽中的方法访问为每个请求接收的原始响应(作为字节数组) 。
通过覆盖QNetworkAccessManager::createRequest()
您自己的网络访问管理器中的方法,可以拦截请求。在那里,您可以访问请求中发送的 URL 和标头并更改它们或取消请求。
但是......您想要访问请求并为每个请求回复数据。
createRequest()
访问请求很容易,在 custom中对方法的覆盖已经解释了这一点QNetworkAccessManager
。但是让我们谈谈另一部分:
对于我所看到的,从请求中获得的回复是只读的并且它不能被更改,因为它在源代码中是硬编码的QNetworkReply
。
您不能使用的writeData()
功能QNetworkReply
,因为它是硬编码的return -1
!
您可以尝试继承QNetworkReply
您自己的 a 并在createRequest()
custom 的方法中返回它QNetworkAccessManager
。您必须覆盖函数readAll()
、bytesAvailable()
和abort()
。奇怪的是,此方法仅在向非 HTTP 目的地发出请求时才有效。我认为内部QNetworkAccessManager
调用QNetworkReply
取决于所使用的协议(HTTP,FTP,...)的不同实现。所以这在某种意义上是有效的,但不是我们想要的方式。例如,此方法可用于在某些条件下返回预定义的网页。
考虑到QNetworkAccessManager::createRequest()
必须返回一个QNetworkReply
对象的事实,我看不到任何允许篡改回复字节数组的子类组合。它受到了很好的保护,您必须重新实现这些类的所有内容才能实现您的目标。几乎复制粘贴所有部分的源类QtNetwork
并制作自己的实现。
所以我认为答案是:“不,似乎不能完全按照你的要求完成;只是部分地”。
对不起。
看起来你想要 Wireshark http://www.wireshark.org/或 Fiddler http://www.fiddler2.com/fiddler2/,甚至可能是 Charles http://www.charlesproxy.com/。
这些工具与 Qt 没有任何关系,可用于检查和拦截各种程序的 Web 流量。
...代理服务器呢?睡个好觉让我想到了这种可能性。
您可以按照环回示例和洪流客户端示例等进行制作。因此,您可以捕获和篡改请求和回复。
您可以QWebView
使用webView->page()->networkAccessManager()->setProxy()
.
这涉及到侦听所需端口(例如 8080)并侦听本地主机上的连接的进程的构建。
您必须通过以下方式实现代理协议:
在这里我没有经验,但路径似乎很清楚。这将是很多编码,但我认为如果不是唯一的选择,这确实是一个不错的选择。
更重要的是:可以做到!