Qt 5.8 Apple Notification Server握手失败

时间:2017-06-30 06:01:41

标签: qt ssl apple-push-notifications ssl-certificate qsslsocket

我现在尝试了一些,但我无法让它工作。我想从Qt应用程序中推送一些通知。尝试使用Qt 5.8安装在macOS Sierra上工作,在Pi3上使用Qt 5.8。

我用“fastlane pem”创建了我的推送证书,我用“Pusher”进行了测试,它的工作正常。但我不能让它在Qt中工作....

首先是我用来初始化和连接QSslSocket的代码:

QSslSocket * ssl = new QSslSocket;

connect(ssl, &QSslSocket::encrypted, this, &IOSPusher::encrypted );
connect(ssl, static_cast<void(QSslSocket::*)(const QList<QSslError> &)>(&QSslSocket::sslErrors),this,&IOSPusher::sslErrors);
connect(ssl, static_cast<void(QSslSocket::*)(QAbstractSocket::SocketError)>(&QSslSocket::error),this, &IOSPusher::error );
connect(ssl,&QSslSocket::stateChanged,this,&IOSPusher::stateChanged );

加载证书

QString path = QStandardPaths::writableLocation(certificateLocation) + "/apns.pem";

const auto certs =  QSslCertificate::fromPath(path);

if(certs.count() > 0){
    qDebug() << "IOSPusher: Certificate loaded successfully";
}else{
    qDebug() << "Could not load certificate : " + path;
}

QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setCaCertificates(certs);

ssl->setSslConfiguration(config);
ssl->connectToHostEncrypted( gateway.sandbox.push.apple.com,2195 );

这就是我得到的输出:

IOSPusher: Certificate loaded successfully
IOSPusher::stateChanged  QAbstractSocket::HostLookupState
IOSPusher::stateChanged  QAbstractSocket::ConnectingState
IOSPusher::stateChanged  QAbstractSocket::ConnectedState
IOSPusher::error  QAbstractSocket::SocketError(13)
IOSPusher::stateChanged  QAbstractSocket::ClosingState
IOSPusher::stateChanged  QAbstractSocket::UnconnectedState

所以根据Qt文档的错误:

  

QAbstractSocket :: SocketError(13)

表示以下内容:

  

SslHandshakeFailedError

并且

&gt; SSL / TLS握手失败,无法建立加密通道。应该发出sslErrors()信号。

我的情况下不会发出sslErrors()信号....

  

SSL / TLS握手失败,因此连接已关闭(仅在QSslSocket中使用)

我是如何建立与苹果的加密连接的想法或示例?

提前致谢!

1 个答案:

答案 0 :(得分:0)

好的,当我试图从现在得到它的任何人那里得到帮助时经常这样:D

现在对我有用的解决方案是:

使用*.pem创建带有密码的fastlane pem证书(也许它在没有密码的情况下也可以正常工作,但这是我现在尝试的最后一个......并且永远不会改变正在运行的系统哈哈)

 fastlane pem --development -p <private_key_password> -a <your_app_identifier>

然后连接QSslSocket执行以下操作......就像我之前的问题一样......

QSslSocket * ssl = new QSslSocket;
QString path = QStandardPaths::writableLocation(certificateLocation) + "/apns.pem";

connect(ssl, &QSslSocket::encrypted, this, &IOSPusher::encrypted );
connect(ssl, static_cast<void(QSslSocket::*)(const QList<QSslError> &)>(&QSslSocket::sslErrors),this,&IOSPusher::sslErrors);
connect(ssl, static_cast<void(QSslSocket::*)(QAbstractSocket::SocketError)>(&QSslSocket::error),this, &IOSPusher::error );
connect(ssl,&QSslSocket::stateChanged,this,&IOSPusher::stateChanged );

QSslCertificate cert;
const auto certs =  QSslCertificate::fromPath(path);

if(certs.count() > 0){
    cert = certs.at(0);
    qDebug() << "IOSPusher: Certificate loaded successfully";
}else{
    qDebug() << "Could not load certificate : " + path;
    return false;
}

现在,魔法为我做了什么

使用private_key(.pkey)文件,该文件也将使用fastlane pem

创建
//Use the path to the .pkey file from fastlane
QFile keyfile(path + "/apns.pkey");
keyfile.open(QFile::ReadOnly);

//Create the QSslKey as private key
QSslKey privateKey(&keyfile,QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,QByteArray("<private_key_password_from_fastlane>"));
//Close the file
keyfile.close();

将私钥和证书添加到ssl config

QSslConfiguration config = QSslConfiguration::defaultConfiguration();

config.setLocalCertificate(cert);
config.setPrivateKey(privateKey);

正如您在此处所见,我不使用config.setCaCertificates方法,而是使用config.setLocalCertificate方法。那是我的错误......

至少将配置添加到ssl套接字和FIRE!

ssl->setSslConfiguration(config);
ssl->connectToHostEncrypted( "gateway.sandbox.push.apple.com",2195 );

多数人

现在发出encrypted()信号!是啊..