C++ Qt login an https server, no use connect

If you want to perform an HTTPS login in C++ with Qt, without using the connect mechanism (which is usually used for event-driven signal-slot communication), you can handle the network request synchronously or with a separate thread to avoid blocking the main thread.

You can use QNetworkAccessManager::get() or QNetworkAccessManager::post() to make the request. However, for this case, since you're handling the login with credentials, you'll probably need to make a POST request with the appropriate data. For synchronous communication, you can block the main thread and wait for the response.

Here's how you can do it synchronously without using connect:

Synchronous Example (Blocking Call):

复制代码

cpp

复制代码
`#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QSslConfiguration>
#include <QSslSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QTimer>
#include <QEventLoop>
#include <QDebug>

int SGServerManage::LoginHttpsServerWithResponse(const QString& sUrl, const QString& sUser, const QString& sPassword, QString& sResponse, QString& sToken) {
    // Create a network manager instance
    QNetworkAccessManager networkManager(this);

    // Construct the URL and create a request
    QUrl qUrl(sUrl);
    QNetworkRequest request(qUrl);

    // Set content type header
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    // Configure SSL settings for the request
    QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
    sslConfig.setProtocol(QSsl::TlsV1_2);  // Force TLS 1.2
    sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);  // Ignore SSL certificate verification (for self-signed certs)
    request.setSslConfiguration(sslConfig);

    // Set ciphers for the SSL connection
    QList<QSslCipher> ciphers;
    ciphers.append(QSslCipher("TLS_AES_128_GCM_SHA256"));
    ciphers.append(QSslCipher("TLS_AES_256_GCM_SHA384"));
    sslConfig.setCiphers(ciphers);
    request.setSslConfiguration(sslConfig);

    // Prepare the request body with the user credentials
    QJsonObject jsonBody;
    jsonBody["username"] = sUser;
    jsonBody["password"] = sPassword;

    QJsonDocument jsonDoc(jsonBody);
    QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Compact);

    // Send the POST request and block until the response is received
    QNetworkReply* reply = networkManager.post(request, jsonData);

    // Wait for the request to finish (blocking)
    QEventLoop loop;
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    loop.exec();  // This will block until the reply is finished

    // Handle the reply
    int result = -1;
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "Error:" << reply->errorString();
        sToken.clear();
        sResponse = reply->errorString();
        result = -1;
    } else {
        QByteArray response = reply->readAll();
        qDebug() << "Response:" << response;
        sResponse = QString::fromUtf8(response);

        QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
        if (jsonDoc.isObject()) {
            QJsonObject jsonObj = jsonDoc.object();

            if (jsonObj.contains("token")) {
                sToken = jsonObj["token"].toString();
                qDebug() << "Token:" << sToken;
                result = 0;
            } else {
                qDebug() << "Token not found in the response.";
                sToken.clear();
                result = -2;
            }
        } else {
            qDebug() << "Invalid JSON response.";
            sToken.clear();
            result = -3;
        }
    }

    // Clean up
    reply->deleteLater();

    return result;
}
`

cpp

Explanation:

  1. Blocking Behavior : Instead of using connect and asynchronous signal-slot connections, I used QEventLoop and connected the finished signal of the QNetworkReply to quit the loop. This makes the network request block until a response is received.

  2. POST Request : The request is sent using networkManager.post(request, jsonData), and the response is handled synchronously once it's finished.

  3. SSL Configuration : I've set the SSL configuration to enforce the use of TLSv1_2 and ignore SSL verification errors (QSslSocket::VerifyNone), which is commonly used when working with self-signed certificates. However, for production, you'd want to ensure proper SSL certificate validation.

  4. Event Loop : After sending the request, we wait for the response by using a QEventLoop. This blocks the thread until the finished signal is emitted, indicating the reply is complete.

Thread-Safety Considerations:

  1. Thread Blocking : This approach blocks the calling thread until the network request is finished. If this method is called from the main thread in a GUI application, the UI will freeze while waiting for the server's response. If you need to avoid this, consider moving the request to a worker thread (using QThread or QtConcurrent::run) and still handle it synchronously within that thread.

  2. Single Threaded Usage : If the QNetworkAccessManager is used in multiple threads, each thread should create its own instance of QNetworkAccessManager to ensure thread safety.

  3. GUI Freezing : If you use this in a GUI application, remember that the main thread will be blocked. To avoid this, you can either use asynchronous methods with connect or offload the work to a separate worker thread.

Moving to Asynchronous Handling (No connect)

If you don't want to use connect and still want to perform the task asynchronously, you can handle the response in a worker thread. This allows you to not block the UI while waiting for the response. Here's an example of how to do that:

复制代码

cpp

复制代码
`// Create a worker thread and run the network request asynchronously in that thread
`

Would you like an example of handling this in a worker thread or further explanation on that topic? Let me know!

相关推荐
GIS阵地1 小时前
QgsProviderMetadata 详解(基于 QGIS 3.40.13 API)
数据库·qt·arcgis·oracle·gis·开源软件·qgis
c++逐梦人1 小时前
C++11——— 包装器
开发语言·c++
十年编程老舅2 小时前
Linux 多线程高并发编程:读写锁的核心原理与底层实现
linux·c++·linux内核·高并发·线程池·多线程·多进程
wildlily84272 小时前
C++ Primer 第5版章节题 第十三章(二)
开发语言·c++
xiaoye-duck2 小时前
【C++:unordered_set和unordered_map】 深度解析:使用、差异、性能与场景选择
开发语言·c++·stl
老约家的可汗2 小时前
list 容器详解:基本介绍与常见使用
c语言·数据结构·c++·list
顶点多余3 小时前
线程互斥+线程同步+生产消费模型
java·linux·开发语言·c++
Albert Edison3 小时前
【ProtoBuf 语法详解】更新消息|保留字段|未知字段
开发语言·c++·protobuf
無限進步D3 小时前
算竞常用STL cpp
开发语言·c++·算法·竞赛
南境十里·墨染春水4 小时前
C++ 笔记 深赋值 浅赋值(面向对象)
开发语言·jvm·c++·笔记