[TOC]

QSslSocket Class

QSslSocket 类为客户端和服务端提供了一个 SSL 加密的套接字。

属性方法
头文件#include <QSslSocket>
qmakeQT += network
引入Qt4.3
继承自QTcpSocket

该类最初在 Qt4.3 版本引入。

您可以在 QSslSocket_Obsolete 界面找到过时的成员函数介绍。

注意: 该类所有的函数都是可重入的。

公共成员类型

类型属性
enumPeerVerifyMode { VerifyNone, QueryPeer, VerifyPeer, AutoVerifyPeer }
enumSslMode { UnencryptedMode, SslClientMode, SslServerMode }

公共成员函数

类型函数名
QSslSocket(QObject *parent = nullptr)
virtual~QSslSocket()
voidabort()
voidconnectToHostEncrypted(const QString &hostName, quint16 port, QIODevice::OpenMode mode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)
voidconnectToHostEncrypted(const QString &hostName, quint16 port, const QString &sslPeerName, QIODevice::OpenMode mode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)
qint64encryptedBytesAvailable() const
qint64encryptedBytesToWrite() const
boolflush()
voidignoreSslErrors(const QList<QSslError> &errors)
boolisEncrypted() const
QSslCertificatelocalCertificate() const
QList<QSslCertificate>localCertificateChain() const
QSslSocket::SslModemode() const
QVector<QOcspResponse>ocspResponses() const
QSslCertificatepeerCertificate() const
QList<QSslCertificate>peerCertificateChain() const
intpeerVerifyDepth() const
QSslSocket::PeerVerifyModepeerVerifyMode() const
QStringpeerVerifyName() const
QSslKeyprivateKey() const
QSsl::SslProtocolprotocol() const
QSslCiphersessionCipher() const
QSsl::SslProtocolsessionProtocol() const
voidsetLocalCertificate(const QSslCertificate &certificate)
voidsetLocalCertificate(const QString &path, QSsl::EncodingFormat format = QSsl::Pem)
voidsetLocalCertificateChain(const QList<QSslCertificate> &localChain)
voidsetPeerVerifyDepth(int depth)
voidsetPeerVerifyMode(QSslSocket::PeerVerifyMode mode)
voidsetPeerVerifyName(const QString &hostName)
voidsetPrivateKey(const QSslKey &key)
voidsetPrivateKey(const QString &fileName, QSsl::KeyAlgorithm algorithm = QSsl::Rsa, QSsl::EncodingFormat format = QSsl::Pem, const QByteArray &passPhrase = QByteArray())
voidsetProtocol(QSsl::SslProtocol protocol)
voidsetSslConfiguration(const QSslConfiguration &configuration)
QSslConfigurationsslConfiguration() const
QList<QSslError>sslHandshakeErrors() const
boolwaitForEncrypted(int msecs = 30000)

重写公共成员函数

类型函数名
virtual boolatEnd() const override
virtual qint64bytesAvailable() const override
virtual qint64bytesToWrite() const override
virtual boolcanReadLine() const override
virtual voidclose() override
virtual voidresume() override
virtual voidsetReadBufferSize(qint64 size) override
virtual boolsetSocketDescriptor(qintptr socketDescriptor, QAbstractSocket::SocketState state = ConnectedState, QIODevice::OpenMode openMode = ReadWrite) override
virtual voidsetSocketOption(QAbstractSocket::SocketOption option, const QVariant &value) override
virtual QVariantsocketOption(QAbstractSocket::SocketOption option) override
virtual boolwaitForBytesWritten(int msecs = 30000) override
virtual boolwaitForConnected(int msecs = 30000) override
virtual boolwaitForDisconnected(int msecs = 30000) override
virtual boolwaitForReadyRead(int msecs = 30000) override

公共槽函数

类型函数名
voidignoreSslErrors()
voidstartClientEncryption()
voidstartServerEncryption()

信号

类型函数名
voidencrypted()
voidencryptedBytesWritten(qint64 written)
voidmodeChanged(QSslSocket::SslMode mode)
voidnewSessionTicketReceived()
voidpeerVerifyError(const QSslError &error)
voidpreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
voidsslErrors(const QList<QSslError> &errors)

静态成员函数

类型函数名
longsslLibraryBuildVersionNumber()
QStringsslLibraryBuildVersionString()
longsslLibraryVersionNumber()
QStringsslLibraryVersionString()
boolsupportsSsl()

重写保护成员函数

类型函数名
virtual qint64readData(char *data, qint64 maxlen) override
virtual qint64writeData(const char *data, qint64 len) override

详细介绍

QSslSocket 能够建立一个安全的、加密的 TCP 连接,您可以使用该连接来传输加密数据。在服务器端和客户端都可以使用它,并且他支持现代的 SSL 协议,包括 SSL 3 和 TLS 1.2。默认情况下,QSslSocket 仅仅使用被认为是安全的( QSsl::SecureProtocols ) SSL 协议,但是只要处在握手开始之前,您仍然可以调用 setProtocol() 函数来更改 SSL 协议。

在套接字进入 已连接ConnectedState )状态后,SSL 将在现有 TCP 流上进行加密。有两种使用 QSslSocket 建立安全连接的简单方法:使用即时 SSL 握手,或在未加密模式下建立连接之后的延迟 SSL 握手。

最常见的 QSslSocket 使用方法是构造一个对象后使用 connectToHostEncrypted() 函数开启一个安全连接,这种方法会在连接建立后开启一个即时的 SSL 握手。

 QSslSocket *socket = new QSslSocket(this);
 connect(socket, SIGNAL(encrypted()), this, SLOT(ready()));

 socket->connectToHostEncrypted("imap.example.com", 993);

与普通的 QTcpSocket 相同,若成功建立连接, QSslSocket 会依次进入 HostLookupStateConnectingStateConnectedState 状态。连接成功后,握手会自动开始,若握手连接成功,QSsslSocket 将会发送 encrypted() 信号,表明该套接字已经进入加密状态并准备好使用。

请注意,在 connectToHostEncrypted() 函数执行完成返回后(即 encrypted() 信号发出之前)数据就可以立即写入套接字。此时写入到套接字的数据将会被加入等待队列,直到 encrypted() 信号被发出。

使用延迟 SSL 握手来保护现有连接的示例是 SSL 服务器保护传入连接。

假设您继承 QTcpServer 类创建了一个 SSL 服务器类。您需要如下例重写 QTcpServer::incomingConnection() :首先构造一个 QSslSocket 对象并调用 setSocketDescriptor() 函数将新的套接字描述符设置为传入的已有的套接字描述符。然后调用 startServerEncryption() 函数初始化 SSL 握手。

 void SslServer::incomingConnection(qintptr socketDescriptor)
 {
     QSslSocket *serverSocket = new QSslSocket;
     if (serverSocket->setSocketDescriptor(socketDescriptor)) {
         addPendingConnection(serverSocket);
         connect(serverSocket, &QSslSocket::encrypted, this, &SslServer::ready);
         serverSocket->startServerEncryption();
     } else {
         delete serverSocket;
     }
 }

如果出现了错误, QSslSocket 将会发出 sslErrors() 信号。在这种情况下,如果没有采取任何操作去忽略出现的错误,该连接将会掉线。若要出现错误后仍然继续维持连接,您可以在错误发生后的槽函数中,或者 QSslSocket 对象构建后、尝试连接之前,调用 ignoreSslErrors() 函数。ignoreSslErrors() 函数将允许 QSslSocket 忽略在建立对等方身份时遇到的错误。 应谨慎使用 ignoreSslErrors() 函数忽略SSL握手期间的错误,因为安全连接的基本特征是应该通过成功的握手来建立它们。

连接加密后,您可以像普通的 QTcpSocket 类一样使用 QSslSocket。当 readyRead() 信号发出后,您可以调用 read(),canReadLine() 和 readLine() 或者 getChar() 从 QSslSocket 的内部缓冲区中读取加密数据,然后您可以调用 write() 或者 putChar() 向对等端写回数据。 QSslSocket 将会自动将您写入的数据加密并在数据写入到对等端后发送 encryptedBytesWritten() 信号。

方便起见,QSslSocket 支持 QTcpSocket 的阻塞函数:waitForConnected(),waitForReadyRead(),waitForBytesWritten() 和 waitForDisconnected()。它也提供了 waitForEncrypted() 函数来在加密连接建立之前阻塞调用的线程。

 QSslSocket socket;
 socket.connectToHostEncrypted("http.example.com", 443);
 if (!socket.waitForEncrypted()) {
     qDebug() << socket.errorString();
     return false;
 }

 socket.write("GET / HTTP/1.0\r\n\r\n");
 while (socket.waitForReadyRead())
     qDebug() << socket.readAll().data();

QSslSocket 提供了广泛的、易于使用的 API ,用于处理密码,私钥以及本地,对等端和证书颁发机构(CA)证书。它也为处理握手阶段出现的错误提供了 API 支持。

以下的特性也可以被客制化:

To extend the list of default CA certificates used by the SSL sockets during the SSL handshake you must update the default configuration, as in the snippet below:

 QList<QSslCertificate> certificates = getCertificates();
 QSslConfiguration configuration = QSslConfiguration::defaultConfiguration();
 configuration.addCaCertificates(certificates);
 QSslConfiguration::setDefaultConfiguration(configuration);

Note: If available, root certificates on Unix (excluding macOS) will be loaded on demand from the standard certificate directories. If you do not want to load root certificates on demand, you need to call either QSslConfiguration::defaultConfiguration().setCaCertificates() before the first SSL handshake is made in your application (for example, via passing QSslSocket::systemCaCertificates() to it), or call QSslConfiguration::defaultConfiguration()::setCaCertificates() on your QSslSocket instance prior to the SSL handshake.

For more information about ciphers and certificates, refer to QSslCipher and QSslCertificate.

This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/).

Note: Be aware of the difference between the bytesWritten() signal and the encryptedBytesWritten() signal. For a QTcpSocket, bytesWritten() will get emitted as soon as data has been written to the TCP socket. For a QSslSocket, bytesWritten() will get emitted when the data is being encrypted and encryptedBytesWritten() will get emitted as soon as data has been written to the TCP socket.

注意

另外您也可以在 QSslCertificateQSslCipherQSslError 类文档中找到相关信息。

成员类型文档

enum QSslSocket::PeerVerifyMode


enum QSslSocket::SslMode

成员函数文档

QSslSocket::QSslSocket**(QObject *parent = nullptr)

[signal] void QSslSocket::encrypted()

[signal] void QSslSocket::encryptedBytesWritten(qint64 written)

[slot] void QSslSocket::ignoreSslErrors()

[signal] void QSslSocket::modeChanged(QSslSocket::SslMode mode)

[signal] void QSslSocket::newSessionTicketReceived()

[signal] void QSslSocket::peerVerifyError(const QSslError &error)

[signal] void QSslSocket::preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)

[signal] void QSslSocket::sslErrors(const QList<QSslError> &errors)

[slot] void QSslSocket::startClientEncryption()

[slot] void QSslSocket::startServerEncryption()

[virtual] QSslSocket::~QSslSocket()

void QSslSocket::abort()

[override virtual] bool QSslSocket::atEnd() const

[override virtual] qint64 QSslSocket::bytesAvailable() const

[override virtual] qint64 QSslSocket::bytesToWrite() const

[override virtual] bool QSslSocket::canReadLine() const

[override virtual] void QSslSocket::close()

void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port, QIODevice::OpenMode mode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)

void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port, const QString &sslPeerName, QIODevice::OpenMode mode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)

qint64 QSslSocket::encryptedBytesAvailable() const

qint64 QSslSocket::encryptedBytesToWrite() const

bool QSslSocket::flush()

void QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)

bool QSslSocket::isEncrypted() const

QSslCertificate QSslSocket::localCertificate() const

QList<QSslCertificate> QSslSocket::localCertificateChain() const

QSslSocket::SslMode QSslSocket::mode() const

QVector<QOcspResponse> QSslSocket::ocspResponses() const

QSslCertificate QSslSocket::peerCertificate() const

QList<QSslCertificate> QSslSocket::peerCertificateChain() const

int QSslSocket::peerVerifyDepth() const

QSslSocket::PeerVerifyMode QSslSocket::peerVerifyMode() const

QString QSslSocket::peerVerifyName() const

QSslKey QSslSocket::privateKey() const

QSsl::SslProtocol QSslSocket::protocol() const

[override virtual protected] qint64 QSslSocket::readData(char *data, qint64 maxlen)

[override virtual] void QSslSocket::resume()

QSslCipher QSslSocket::sessionCipher() const

QSsl::SslProtocol QSslSocket::sessionProtocol() const

void QSslSocket::setLocalCertificate(const QSslCertificate &certificate)

void QSslSocket::setLocalCertificate(const QString &path, QSsl::EncodingFormat format = QSsl::Pem)

void QSslSocket::setLocalCertificateChain(const QList<QSslCertificate> &localChain)

void QSslSocket::setPeerVerifyDepth(int depth)

void QSslSocket::setPeerVerifyMode(QSslSocket::PeerVerifyMode mode)

void QSslSocket::setPeerVerifyName(const QString &hostName)

void QSslSocket::setPrivateKey(const QSslKey &key)

void QSslSocket::setPrivateKey(const QString &fileName, QSsl::KeyAlgorithm algorithm = QSsl::Rsa, QSsl::EncodingFormat format = QSsl::Pem, const QByteArray&passPhrase = QByteArray())

void QSslSocket::setProtocol(QSsl::SslProtocol protocol)

[override virtual] void QSslSocket::setReadBufferSize(qint64 size)

[override virtual] void QSslSocket::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)

void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)

[override virtual] QVariant QSslSocket::socketOption(QAbstractSocket::SocketOption option)

QSslConfiguration QSslSocket::sslConfiguration() const

QList<QSslError> QSslSocket::sslHandshakeErrors() const

[static] long QSslSocket::sslLibraryBuildVersionNumber()

[static] QString QSslSocket::sslLibraryBuildVersionString()

[static] long QSslSocket::sslLibraryVersionNumber()

[static] QString QSslSocket::sslLibraryVersionString()

[static] bool QSslSocket::supportsSsl()

[override virtual] bool QSslSocket::waitForBytesWritten(int msecs = 30000)

[override virtual] bool QSslSocket::waitForConnected(int msecs = 30000)

[override virtual] bool QSslSocket::waitForDisconnected(int msecs = 30000)

bool QSslSocket::waitForEncrypted(int msecs = 30000)

[override virtual] bool QSslSocket::waitForReadyRead(int msecs = 30000)

[override virtual protected] qint64 QSslSocket::writeData(const char *data, qint64 len)