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

发布于:2025-03-02 ⋅ 阅读:(94) ⋅ 点赞:(0)

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!


网站公告

今日签到

点亮在社区的每一天
去签到