gpt4 book ai didi

c++ - 如何让 QNetworkReply 返回自定义数据?

转载 作者:行者123 更新时间:2023-11-30 01:09:13 27 4
gpt4 key购买 nike

我将使用 QNetworkAccessManager 通过我的移动应用向服务器发出对 HTTP 服务器的请求。问题是,如何将自定义数据链接到每个请求?我尝试子类化 QNetworkReply 但我发现我必须实现虚拟方法 close()isSequential() 但我不知道它们应该返回什么所以我是恐怕我会破坏网络请求功能。

例如,当我的应用执行登录程序时,它必须存储帐户的电子邮件地址:

class MyApp : public QObject
{
Q_OBJECT

private:
QNetworkRequest request;
QNetworkReply *reply;
QNetworkAccessManager *manager;

...

}

void MyApp::do_log_in(QString email, QString password) {
QString s;

someobject.email=email; // <-- I have to store email address before sending request to server, but where do I store it?
s.append("http://myapp.com/do-auth.php?email=");
s.append(QUrl::toPercentEncoding(email));
s.append("&password=");
s.append(QUrl::toPercentEncoding(password));
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(login_finished(QNetworkReply*)));
request.setUrl(QUrl(s));
manager->get(request);

}

void MyApp::login_finished(QNetworkReply *rep) {
DepservReply *reply;
QString email;
....
email= ...... // <-- I need to get the email address from QNetworkReply object somehow
///my code here handling server reply
....
}

那么,在我的案例中,我该如何实现电子邮件的存储和检索,我应该子类化哪些类以及我应该重新实现哪些方法?

最佳答案

您可以利用每个 QObject 中可用的动态属性系统并将数据保存在回复中:

// https://github.com/KubaO/stackoverflown/tree/master/questions/network-reply-tracking-40707025
#include <QtNetwork>

class MyCtl : public QObject
{
Q_OBJECT
QNetworkAccessManager manager{this};
// ...
void reply_finished(QNetworkReply *reply);
public:
MyCtl(QObject *parent = nullptr);
void do_log_in(const QString &email, const QString &password);
};

static const char kAuthGetSalt[] = "req_auth-get-salt";
static const char kDoAuth[] = "req_do-auth";
static const char kEmail[] = "req_email";
static const char kPassword[] = "req_password";

static const auto authGetSaltUrl = QStringLiteral("https://myapp.com/auth-get-salt.php?email=%1");
static const auto doAuthUrl = QStringLiteral("https://myapp.com/do-auth.php?email=%1&passwordHash=%2");

MyCtl::MyCtl(QObject *parent) : QObject{parent}
{
connect(&manager, &QNetworkAccessManager::finished, this, &MyCtl::reply_finished);
}

void MyCtl::do_log_in(const QString &email, const QString &password) {
auto url = authGetSaltUrl.arg(email);
auto reply = manager.get(QNetworkRequest{url});
reply->setProperty(kAuthGetSalt, true);
reply->setProperty(kEmail, email);
reply->setProperty(kPassword, password);
}

void MyCtl::reply_finished(QNetworkReply *reply) {
if (!reply->property(kAuthGetSalt).isNull()) {
reply->deleteLater(); // let's not leak the reply
if (reply->error() == QNetworkReply::NoError) {
auto salt = reply->readAll();
auto email = reply->property(kEmail).toString();
auto password = reply->property(kPassword).toString();
Q_ASSERT(!password.isEmpty() && !email.isEmpty());
QCryptographicHash hasher{QCryptographicHash::Sha1};
hasher.addData(salt); // the server must hash the same way
hasher.addData("----");
hasher.addData(password.toUtf8());
auto hash = hasher.result().toBase64(QByteArray::Base64UrlEncoding);
auto url = doAuthUrl.arg(email).arg(QString::fromLatin1(hash));

auto reply = manager.get(QNetworkRequest{url});
reply->setProperty(kDoAuth, true);
reply->setProperty(kEmail, email);
}
}
else if (!reply->property(kDoAuth).isNull()) {
if (reply->error() == QNetworkReply::NoError) {
auto email = reply->property(kEmail).toString();
// ...
}
}
}

通过让编译器检查您使用的标识符是否有效,将常量用作属性名称以避免拼写错误。

上面的示例纠正了代码中的以下关键安全问题:

  1. 通过清晰的连接发送安全凭证:使用 https://,而不是 http://

  2. 以明文形式发送密码:相反,发送密码的加盐哈希值。创建帐户时,您的服务器应该为每个帐户生成一个随机盐。现有帐户可以不加盐,但一旦用户更改密码,它们就应该加盐。

另请注意,QStringQUrl 的转换将自动对字符串进行百分号编码,因此无需显式执行此操作。

关于c++ - 如何让 QNetworkReply 返回自定义数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40707025/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com