配置QSslConfiguration让客户端程序跳过本地SSL验证



  • 大家下午好哦。今天我们在重新制作我们萌梦聊天室的时候,出现了这样的问题。那就是我们的客户端能够对qtdream.com服务器进行登录,但是不能对localhost服务器(也就是本机啦)进行登录。这究竟是什么原因呢?
    原图来自http://www.pixiv.net/member_illust.php?mode=medium&illust_id=60269167
    因为这个问题是在我们引入了https的时候出现的,所以我们把原因定位到为什么会导致https出现问题。后面我看到了QNetworkRequest这个类,看到了里面有这样一个函数::strawberry:

    QNetworkRequest::setSslConfiguration(const QSslConfiguration &configuration);
    

    这个函数呢,可以设置SSL的配置,包括OpenSSL以及其它的SSL,都是这样的配置。然后我又看QSslConfiguration这个类:,并且看到了这样的函数:

    QSslSocket::setPeerVerifyMode(QSslSocket::PeerVerifyMode mode);
    

    我在仔细研读文档后,发现其中的端倪。原来默认设置是对服务器的安全证书进行验证的。我们本地的网站由于证书有问题,从而无法导入证书,这个时候呢,无法通过验证。这个时候,默认的验证模式无法通过,从而服务端无法获得到客户端传入的数据,因此我们需要进行这样的操作:

        // 设置SSL配置
        QSslConfiguration sslConf;
        sslConf.setPeerVerifyMode( QSslSocket::VerifyNone );
        r.setSslConfiguration( sslConf );
    

    这样操作的话,我们就可以不再检测SSL了。这样我们就可以顺利地通过我们的客户端连接到我们的服务器了。怎样?很简单吧。



  • 既然是VerifyNone,那还要QSslConfiguration干什么?完全去掉QSslConfiguration可以吗?



  • @stlcours 因为不配置这个,会采用默认的配置,导致我的聊天室软件连不上我的https的服务器。



  • 所以只是对本机登录不行的。对远程登录https://qtdream.com这边儿是可以的。



  • @jiangcaiyang123 你好,我正在学习QWebSocket编程,跟着示例做了服务器和客户端,服务器设置了VerifyNone,也生成了证书。客户端没有生成证书,因为服务器端设置了verifyNone。然后在同一台机器上运行测试,也就是这里所说的客户端连接本地服务器,但是客户端的state一直停留在connectingState,服务器端没有任何回馈,然后就一直这个状态,没有后续,没有emit任何错误。
    1.试过在客户端设置VerifyNone,无效
    2.试过在客户端生成证书,也无效
    3.试过非安全模式,成功,但没意义。

    困扰好几天了,请问你是怎么建立连接的?望指教

    平台是mac os sierra
    附上我的代码:
    服务器端:
    #include "fd_sslwebsocket_server.h"

    #include "fd_sslwebsocket_server.h"
    #include "QtWebSockets/QWebSocketServer"
    #include "QtWebSockets/QWebSocket"
    #include <QtCore/QDebug>
    #include <QtCore/QFile>
    #include <QtNetwork/QSslCertificate>
    #include <QtNetwork/QSslKey>

    QT_USE_NAMESPACE

    fd_sslwebsocket_server::fd_sslwebsocket_server(quint16 port, QObject *parent) :
    QObject(parent),
    m_pWebSocketServer(Q_NULLPTR),
    m_clients()
    {
    m_pWebSocketServer = new QWebSocketServer(QStringLiteral("SSL Echo Server"),
    QWebSocketServer::SecureMode,
    this);

      QSslConfiguration sslConfiguration;
      QFile certFile(QStringLiteral(":/ssl/test/CARoot1024.cert"));
      QFile keyFile(QStringLiteral(":/ssl/test/CARoot1024.key"));
      certFile.open(QIODevice::ReadOnly);
      keyFile.open(QIODevice::ReadOnly);
      QSslCertificate certificate(&certFile, QSsl::Pem);
      QSslKey sslKey(&keyFile, QSsl::Rsa, QSsl::Pem);
      certFile.close();
      keyFile.close();
      sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
      sslConfiguration.setLocalCertificate(certificate);
      sslConfiguration.setPrivateKey(sslKey);
      sslConfiguration.setProtocol(QSsl::TlsV1SslV3);
      m_pWebSocketServer->setSslConfiguration(sslConfiguration);
    
    
      if (m_pWebSocketServer->listen(QHostAddress::Any, port))
      {
          qDebug() << "SSL Echo Server listening on port" << port;
          connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
                  this, &fd_sslwebsocket_server::onNewConnection);
          connect(m_pWebSocketServer, &QWebSocketServer::sslErrors,
                  this, &fd_sslwebsocket_server::onSslErrors);
          connect(m_pWebSocketServer, &QWebSocketServer::peerVerifyError,
                  this, &fd_sslwebsocket_server::onPeerVerifyError);
      }
    

    }

    void fd_sslwebsocket_server::onPeerVerifyError(const QSslError &error)
    {
    qDebug() << error;
    }

    fd_sslwebsocket_server::~fd_sslwebsocket_server()
    {
    m_pWebSocketServer->close();
    qDeleteAll(m_clients.begin(), m_clients.end());
    }

    void fd_sslwebsocket_server::onNewConnection()
    {
    QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();

      qDebug() << "Client connected:" << pSocket->peerName() << pSocket->origin();
    
      connect(pSocket, &QWebSocket::textMessageReceived, this, &fd_sslwebsocket_server::processTextMessage);
      connect(pSocket, &QWebSocket::binaryMessageReceived,
              this, &fd_sslwebsocket_server::processBinaryMessage);
      connect(pSocket, &QWebSocket::disconnected, this, &fd_sslwebsocket_server::socketDisconnected);
      //connect(pSocket, &QWebSocket::pong, this, &fd_sslwebsocket_server::processPong);
    
      m_clients << pSocket;
    

    }

    void fd_sslwebsocket_server::processTextMessage(QString message)
    {
    QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
    qDebug() << "Received message:" << message;
    if (pClient)
    {
    pClient->sendTextMessage(message);
    }
    }

    void fd_sslwebsocket_server::processBinaryMessage(QByteArray message)
    {
    QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
    if (pClient)
    {
    pClient->sendBinaryMessage(message);
    }
    }

    void fd_sslwebsocket_server::socketDisconnected()
    {
    qDebug() << "Client disconnected";
    QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
    if (pClient)
    {
    m_clients.removeAll(pClient);
    pClient->deleteLater();
    }
    }

    void fd_sslwebsocket_server::onSslErrors(const QList<QSslError> &)
    {
    qDebug() << "Ssl errors occurred";
    }


    客户端:
    #include "fd_sslwebsocket_client.h"
    #include <QtCore/QDebug>
    #include <QtWebSockets/QWebSocket>
    #include <QCoreApplication>

    #include <QtCore/QFile>
    #include <QtNetwork/QSslCertificate>
    #include <QtNetwork/QSslKey>

    QT_USE_NAMESPACE

    fd_sslwebsocket_client::fd_sslwebsocket_client(const QUrl &url, QObject *parent) :
    QObject(parent),
    m_webSocket()
    {

    /*
    QSslConfiguration sslConfiguration;

      QFile certFile(QStringLiteral(":/ssl/test/CARoot1024.cert"));
      QFile keyFile(QStringLiteral(":/ssl/test/CARoot1024.key"));
      certFile.open(QIODevice::ReadOnly);
      keyFile.open(QIODevice::ReadOnly);
      QSslCertificate certificate(&certFile, QSsl::Pem);
      QSslKey sslKey(&keyFile, QSsl::Rsa, QSsl::Pem);
      certFile.close();
      keyFile.close();
    
      sslConfiguration.setLocalCertificate(certificate);
      sslConfiguration.setPrivateKey(sslKey);
    
      sslConfiguration.setProtocol(QSsl::TlsV1SslV3);
      sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyPeer);
      m_webSocket.setSslConfiguration(sslConfiguration);
    

    */

      connect(&m_webSocket, &QWebSocket::connected, this, &fd_sslwebsocket_client::onConnected);
    
      connect(&m_webSocket, static_cast<void(QWebSocket::*)(QAbstractSocket::SocketError)>(&QWebSocket::error), this,  &fd_sslwebsocket_client::onError);
    
      typedef void (QWebSocket:: *sslErrorsSignal)(const QList<QSslError> &);
      connect(&m_webSocket, static_cast<sslErrorsSignal>(&QWebSocket::sslErrors),
              this, &fd_sslwebsocket_client::onSslErrors);
    
      connect(&m_webSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
                        this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
    
      m_webSocket.open(QUrl(url));
      qDebug() << "Starting open..." << url;
    

    }

    void fd_sslwebsocket_client::socketStateChanged(QAbstractSocket::SocketState state)
    {
    qDebug() << "state:" << state;
    }

    void fd_sslwebsocket_client::onError(QAbstractSocket::SocketError error)
    {
    qDebug() << "error code:" << error << ". error string" << m_webSocket.errorString();
    }

    void fd_sslwebsocket_client::onConnected()
    {

      qDebug() << "WebSocket connected";
      connect(&m_webSocket, &QWebSocket::textMessageReceived,
              this, &fd_sslwebsocket_client::onTextMessageReceived);
    
      m_webSocket.sendTextMessage(QStringLiteral("Hello, world!"));
    
      int lv_count = 0;
      while (lv_count < 10000) {
          m_webSocket.sendTextMessage(QStringLiteral("Hello, world!") + QString::number(lv_count, 10));
          lv_count++;
      }
      qApp->quit();
    

    }

    void fd_sslwebsocket_client::onTextMessageReceived(QString message)
    {
    qDebug() << "Message received:" << message;
    //qApp->quit();
    }

    void fd_sslwebsocket_client::onSslErrors(const QList<QSslError> &errors)
    {
    Q_UNUSED(errors);

      // WARNING: Never ignore SSL errors in production code.
      // The proper way to handle self-signed certificates is to add a custom root
      // to the CA store.
    
      qDebug() << m_webSocket.errorString();
    
      //m_webSocket.ignoreSslErrors();
    

    }



  • @shwth33 用SSL的key和cer来验证的吗?这个我没有尝试过,我好像只是用open(),没有那么复杂的样子啊。


登录后回复
 

与 萌梦社区 的连接断开,我们正在尝试重连,请耐心等待