推送系列二:流程及其安全性

Paste_Image.png

引言

我们日常使用的大多数app几乎第一次启动都会弹出一堆权限获取的alert交互框,这类alert会阻塞用户的使用进程,所以很多用户为了快速使用app,都会随便地点击其中任一按钮以便快速过渡这个状态,这样其实很容易陷入app的一些“黑洞”中,比如某些app对摄像头权限的获取,可能在不经意间打开用户手机的摄像头获取到隐私信息;某些app对通讯录权限的获取,可能会将个人信息泄露;而与我们本文相关的推送相关的权限,app可能在以下方面对用户有所影响:

  1. 可能有频繁的及时消息弹出框
  2. 可能有偶尔的广告弹出框

本文不会讲述如何避开这些“黑洞”, 而是讲述“黑洞”之一----推送,因为推送对用户体验如此大的影响,iOS系统制定了一套严密的机制, 本文对实现流程进行介绍的同时,着重讲解其中对安全性的考虑: 简单来说就是,首先保证只有认证的开发者的app可以推送,其他人无法通过手段干扰此app的推送操作,其次必须用户许可才能接受推送,并且用户可以随时取消推送通知。

流程

下面首先介绍推送实现的流程,如下图:



技术上我们可以简化为:


image

上面的流程包含:

  1. 建立安全通道;
  2. 注册服务,请求token:app通过APNs提供的api,向iOS系统注册推送服务,系统将请求转发给APNs服务器,服务器将device token反馈给iOS设备,通过APNs提供的api传给app;
  3. app将获取到的token上传给自己的服务器
  4. 当存在需要推送的消息时,自己的服务器将消息内容、提醒形式、token等信息发送给APNs服务器;
  5. APNs服务器根据需要推送消息的token,获取到token对应的设备是否在线,如果设备在线,则将消息推送给设备,由系统将推送消息通过定义的形式展示或者提示出来。

注意:

当设备由于无网络等情况不在线时,app中与网络相关服务将无法使用,推送也无法到达,因为APNs也是基于网络的长连接来实现,苹果针对这种情况了也提供了保障机制,当离线期间有很多推送时,虽然苹果无法将消息及时推送到指定设备上,但也会基于体验考虑做一定处理,具体可参考官方文档。

流程中的安全性

下面将逐步论证苹果在每个步骤的具体过程和安全机制:

针对第一个步骤:建立安全通道

具体如下图:


image

Trust between APNs and each device is established automatically by the device’s operating system upon initial device activation (and without participation by your app), as described in this section.

需要强调的是,上图中的过程在iOS设备激活的时刻就已经开始进行,是与app本身无关的,是iOS设备本身与APNs服务器之间的沟通建立信任的过程。当这个信任确定成功后,后续这个iOS设备上所有app与APNs服务器之间的沟通都是安全可靠的。
(可参考 https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1

流程中包含四次交互--四次握手:

  1. iOS设备在刚激活时将首先向APNs服务器打招呼--请求tls连接,也就是说建立一个基于tls协议的长连接(这种连接可以在保证双发的身份可信的情况下,对连接后续的通信过程进行加密,保证通信信息的安全保密性。)
  2. APNs服务器收到请求后,将反馈给iOS设备一个APNs服务器的证书;个人理解此时iOS设备已经存有APNs服务器的公钥。
  3. iOS设备收到证书后通过APNs服务器的公钥解密出APNs服务器的证书,与本地存储的证书比对验证通过,将反馈给APNs服务器自己的证书和私钥(通过APNs服务器的公钥加密),二者都是设备激活过程中获得并存在设备的钥匙串中的(并非apple开发者网站上建立的证书)。
  4. APNs服务器接收到后,通过私钥解密出发来的证书(每个出厂的iOS设备应该都有证书存在APNs服务器)验证通过,解密出来的私钥用于后期二者之间的加密通信,握手成功。

针对第二个步骤:注册服务,请求token

第一步建立安全连接后,当app中调用注册推送服务的方法时,需要调用APNs的api:
registerForRemoteNotificationTypes
来注册,APNs服务器首先根据app的bundle id生成一个只跟此app有关的device token,然后将device token加密后发送给设备,设备通过ios系统转发给指定app,app会通过相应的代理方法
applicationdidRegisterForRemoteNotificationsWithDeviceToken
来得知已经注册成功并返回加密后的device token。
通过上面的分析可知,即使device token被第三方截获,也无法模拟用户与APNs服务器进行通信来伪造用户,因为身份验证无法通过,APNs服务器不会信任这个第三方。

注意:

app每次launch必须重新注册推送服务,重新获取device token,因为device token会发生变化,如果APNs服务器存储的不是最新的device token,推送将失败。(device token是个迷,欲了解device token可以参考我的另一篇博文:)

针对第三个步骤:app发送device token给自己的服务器

这一步是需要开发者自己来保证安全的一步,一般我们可以模拟苹果的机制,对device token进行对称加密,或者与服务器协商好撒盐和md5的方式,保证通信过程中即使被截获也无法被破解。当然为了提高安全级别,可以加入认证授权的操作,甚至模仿苹果的tls方式来进一步保证安全性。

针对第四个步骤:provider发送消息给APNs服务器

这一步安全性通常有两种方式来保证:
第一种是经典的做法,也是与设备和APNs服务器相同的做法,即通过建立tls长连接来校验身份,四次握手后开始发送消息。与第一步差别在于第三次握手时传给APNs服务器的apple开发者网站注册的推送证书和私钥。这样APNs服务器可以通过证书判断当前通过信的对方是可信的服务器,连接建立成功,provider便可以给PNs服务器发送推送消息,要求其转发。 如下图:
[图片上传失败...(image-c2a994-1523504685576)]

第二种做法是从iOS9开始苹果推荐的更简便的http2的方式,从下图的这个过程可以看出是对四次握手的改良,我们的服务器第二次握手收到APNs服务器的推送证书后,就已经建立可以信任的连接,后面推送消息将通过基于http2的请求来实现:每次推送的请求都携带者经过我们自己服务器私钥加密过的token,APNs服务器收到请求后首先验证token是否合法,如果合法则证明是可信任的服务器,则将反馈一个成功的response给我们的服务器。连接建立成功,provider便可以给PNs服务器发送推送消息,要求其转发。


image

这一步,provider的请求中header中存放着device token,便于APNs服务器了解这条推送的目的地是哪里。

针对第五个步骤:APNs服务器推送消息到设备

这一步的安全性其实是基于上面注册推送服务时已经建立好的基于tls协议的长连接,这时APNs服务器根据provider的请求中device token使用秘钥解码得到设备的id和app的bundle id, 这样通过设备的id 判断这个设备在线并且可以信任,直接将推送消息发给设备上的对应的app,app中可以通过api来获取到最新一条推送的内容:
didReceiveRemoteNotification 或 applicationdidFinishLaunchingWithOptions
第二个接口对应app已经挂起后用户点击推送的消息弹窗后的响应。

这样,承载着信鸽功能一样的推送就路由到了用户的手机上,给用户一个提示---赶紧去app中查看吧。


Paste_Image.png

但是设备如果不在线呢?
关于这种情况,官方说法是有一种QoS保障: 当设备不在线时,如果收到很多条推送,只保留最后一条推送一定时间,如果超时则舍弃。

Apple Push Notification service includes a default Quality of Service (QoS) component that performs a store-and-forward function. If APNs attempts to deliver a notification and the destination device is offline, APNs stores the notification for a limited period of time and delivers it when the device becomes available again. This component stores only the most recent notification per device and per app. If a device is offline, sending a new notification causes the previous notification to be discarded. If a device remains offline for a long time, all stored notifications are discarded.

我通过微信进行了验证,当手机切到飞行模式后,好友给我连续发10条信息,当我回到正常模式后,只收到最后一条推送。(注意:由于APNs是长连接服务,APNs通过心跳来判断ios设备是否在线,由于我们不知道心跳间隔,当手机刚切入到飞行模式时就发送消息,实际可能会收到10条推送,因为此时APNs判断ios设备还在线,所以不会启动QoS保障,所以验证时请在切入飞行模式1分钟以后)

苹果对推送的建议是不要使用推送作为通信的直接载体,而是作为一种通知形式:

Because the delivery of remote notifications is not guaranteed, never include sensitive data or data that can be retrieved by other means in your payload. Instead, use notifications to alert the user to new information or as a signal that your app has data waiting for it. For example, an email app could use remote notifications to badge the app’s icon or to alert the user that new email is available in a specific account, as opposed to sending the contents of email messages directly. Upon receiving the notification, the app should open a direct connection to your email server to retrieve the email messages.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容