粗略使用OpenSSL编写Apple Push工具
Posted 人生如梦91
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了粗略使用OpenSSL编写Apple Push工具相关的知识,希望对你有一定的参考价值。
好久没有写过博客了, 自从上家公司裁员,加入新公司之后,每天忙的不可开交,需求不断,每天23点下班,感觉一天24小时都不够用。还好现在大忙的时候已经过去了,临近过年,也没有什么太大的需求了,于是有空就写下博客,记录一下自己做的事。
作为一名ios程序员,推送方面的知识是不可能不接触到的,做推送方面的东西又不可能不调试,每次我都是使用NWPusher这个工具来做测试,用起来确实很方便,但是我却不知道到底这个工具是怎么做出来的,我也很想知道,于是看了一波这个工具的代码,熟悉了基本流程之后,就自己尝试着做一个出来。虽然很拙劣,但毕竟也成功的将数据推了过来,主要分为以下几个步骤:
文章目录
1. 准备工作
iOS推送,首先是要有配置证书,应该先前往
苹果开发者中心去配置推送证书,如下图所示:
点击"Create Certificate",创建推送证书,完成之后,下载证书并导入到KeyChain,最终在KeyChain里的效果如下所示:
其中必须包含证书和一个私钥,我将他导出为p12文件,设置密码,保存即可。
2.解析证书
导出了p12, 我就可以加载并解析证书了,我使用OpenSSL库的方法来解析,代码如下图所示:
使用PKCS12_parse方法解析p12文件,得到一个X509的证书和一个EVP_PKEY的私钥和一个STACK_OF(X509)*的根证书,如果有根证书的话。然后我们拿到证书的SubjectName,因为苹果的推送证书都包含了"Apple Development IOS Push Services"(开发环境) 或 “Apple Production IOS Push Services”(生产环境),所以我们只需要匹配字符串,即可判断该证书是否为推送证书。
3.Socket连接
要发送推送,我们首先要连接到苹果的推送服务器,创建socket并建立连接,如下图:
其中,苹果的推送服务器地址如下所示:
我们先使用gethostbyname方法,拿到苹果推送服务器的ip地址,然后连接到2195端口即可
4.建立SSL连接
由于苹果推送服务器使用的是SSL连接,所以我们还需要建立SSL连接,建立的过程如下所示:
创建一个SSL_Ctx上下文,使用解析出来的证书及私钥,并使用SSL_new建立一个新的ssl连接,并用SSL_set_fd设置已建立连接的套接字,再使用SSL_set_connect_state将ssl的状态设置为连接状态,最后使用SSL_do_handshake进行握手连接,握手返加1表示已成功建立SSL连接。
SSL连接建立成功之后,我们可以使用SSL_get_peer_certificate来拿到Apple端的证书,如下所示:
输出结果如下所示:
5.构建推送报文
Apple的推送服务有三种格式,如下图所示,图片根据NWPusher代码绘制,若有错误遗漏,请批评指正。
从图上我们可以看到,推送报文一共有三种格式。
- 第一种第一个字节为command字段,其值固定为0, 之后2个字节是DeviceToken字节长度,固定为32个字节,大端序。然后是DeviceToken, 接下来2个字节为push json的长度,也是大端序,最大为256,最后便是push的内容了。总长度为 37 + Payload_Length.
- 第二种第一个字节为command字段,其值固定为1, 与第一种相比,多了8个字节,其中4个字节用做Thread Identifier 线程标识,另外4个字节用于表示push过期时间戳。总长度为 45 + Payload_Length.
- 第三种最为复杂,第一个字节依然为command字段,其值固定为2, 与前两种相比较,多了一些字段,command字段之后的4个字节用于表示消息长度,即除去command字段和消息长度字段之外的报文总长度,之后即为DeviceToken, Payload Data, Thread Identifier, Expire Timestamp, Priority等字段,分别标识为1,2,3,4,5, 总长度为 58 + Payload_Length.
为了简单起见,我只封装了第一种报文格式,代码如下所示:
这里使用jsoncpp库来做为json的解析工具,如果解析成功,则说明输入的数据是合法的json数据,否则表示json数据有误。
deviceToken为32字节的二进制数据,但是我们输入的是一个字符串,所以我们应该要把64位的字符串转换为32位的二进制数据。其实我这里只是做了简单的处理,并没有包括验证DeviceToken合法性,处理空格等其他字符等流程。
构建完成之后,即可以将数据包发送给Apple Push服务器,代码如下图所示:
调用SSL_write写入数据即可,SSL_write返回值为写入的数据长度。我们这里不做结果验证,简单的认为SSL_write返回正确即认为push成功。
push完成之后,手机即可接收到推送信息,如果要推送多条数据的话,可以继续写入push信息,但不要每写入一条就断开连接再重新连接,如此反复多次,Apple Push服务器可能会禁止本机ip访问。写入结束之后再断开SSL连接,如下所示:
结束
其实写这样一个工具还是蛮简单的,总结起来就是连接-封装-发送-关闭这几个步骤而已,不过因为不懂SSL,所以实现这个功能也花了一点点时间。特此记录,以后有时候可以在此基础上再写一个更完整更健壮的推送测试工具出来。
以上是关于粗略使用OpenSSL编写Apple Push工具的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法确定 Apple Watch 和 iPhone 之间的粗略距离?
Apple 登录“invalid_client”,使用 PHP 和 openSSL 签署 JWT 进行身份验证
Apple 推送通知服务 (APNS):反馈服务响应缺少字节?
iOS push全方位解析译文"——生成OpenSSL证书,Provisioning Profile