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



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

    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(),没有那么复杂的样子啊。



  • @shwth33 你可以在客户端里嵌入一个证书试试。



  • @stlcours 这个问题估计2018年还会出现,我们层经做过静态编译带聊天,曾经实现了,现在由于架构更改了,可能问题又是一大堆吧。


 

最近的回复

  • 0_1539655233041_329385492.jpg
    各位大家好哦。
    经过一个晚上对论坛的维护更新,我们成功地将论坛更新到最新的版本。这次的版本更新主要是提升了稳定性,因此功能上和原来的一样,请大家放心,不会出现奇怪的东西什么的啦。然后呢,由于提升了稳定性,因此论坛不会莫名其妙地出现未响应的情况,总之比以前好就对啦。

    此外,论坛新增了自己研制的一个分享的插件:nodebb-plugin-share-sns-cn。这个插件呢,主要是做主流社交网站的分享的。目前暂时支持QQ、微博以及微信的分享。目前初版是1.0。

    希望大家常常来论坛玩~

    阅读更多
  • 发一些二次元妹子图吧。谁叫我有时候也挺无聊的呢~
    0_1539486167719_119.jpg

    阅读更多
  • 0_1539445819168_123.jpg
    各位大家好!
    又有一段时间啦。我们的萌梦动作编辑器又进行更新啦!☺ ☺
    这次的更新呢,主要是完善了一下自动构建系统。也就是说为了持续构建并且能够给到爱好者可用并且稳定的软件,我们做了很多的努力,其中一点就是制作了脚本进行持续构建,以前要花很多很多的时间对动作编辑器进行构建,现在呢,没有那么复杂了。简简单单地数个批处理操作,即可快速构建咱们的动作编辑器,使得从代码到产品只需要十几分钟即可完成,比以前的速度节省了90%的时间,可谓神速!这套系统已经成功地应用到Windows平台线上了,现在基本可以做到每日构建的水平。而且为每次构建专门准备了pdb文件,即一旦用户运行动作编辑器出现了问题,可以通过程序调试数据库定位到问题的位置,从而提升服务的水平,想想这对于我一直坚持的萌梦这款产品来说算是革命性的操作呢。

    当然现在这套系统只能应用在Windows线上,Mac OS X这条线是我接下来努力的方向,也希望能够实现Mac这条线的每日构建效果。然后Linux平台也比较重要,想起Linux开发应该比Windows等等要方便,所以我想难度比Windows的要小很多,甚至比Mac OS X的都要小。总之路途还很遥远,加油努力吧!

    这次的Windows版本已经成功地在Windows的安装包中进行测试,同时提供在线的和离线的安装包。下面就是这些安装包的github下载地址。

    Windows在线安装包
    Windows离线安装包

    阅读更多
  • 手动给一个赞!!☺ 🤗
    0_1539264026793_好美的图啊.jpg

    阅读更多

关注我们

微博
QQ群











召唤伊斯特瓦尔