iOS开发之新版APNs搭建必备知识

本文的大部分内容是对苹果关于APNs官方文档的翻译以及整理。

一、设备token和消息的生命周期

关于设备token以及推送消息的生命周期需要注意下面几点:

  • Token会在iOS系统更新或者设备数据、设置被擦除的时候改变。
  • 当设备离线的时候,APNS会将消息数据存储一段时间,等设备上线后重发。如果设备在离线期间,向APNS发送了多条推送消息,APNS将会丢弃掉前面的一些消息,只保留后面的消息,要是设备长时间离线,则会将所有的消息丢弃掉。
  • 可以通过设置http/2头中的apns-collapse-id键值对来合并消息,比如:apns-collapse-id : 2,那么value为2的消息将被APNS合并成一条消息推送给设备。

二、Provider(后台)与APNs的交互

Provider(即,APP的后台)与APNS有两种安全的交互方式,都必须采用TLS以保证可靠性,更详细的内容继续往下看。

TLS的简单理解是,为了保证数据传输安全,在HTTP层与TCP层之间插入的一个安全校验层,它所做的事情简单来说就是:“通过CA申请的证书验证client与server是可靠的之后,通过相应的公私钥加密一个协商的公钥,之后的真实数据传输就使用这个公钥进行加密,以保证数据的安全可靠性”,关于TLS的更详细的介绍,可以参考这篇文章

基于Token的方式(Token-Based Provider-to-APNs Trust)

1、流程概述

这种方式适合在基于HTTP/2协议的Provider使用,它与APNs之间的连接通过JWT(JSON web tokens)来验证。在这种方式下不需要使用证书+私钥的方式来建立可靠连接。Provider只需要提供一对公私钥(私钥Provider自己保存,公钥苹果保存),并使用其中的私钥生成并加密JWT Token,每次向APNs请求推送的时候带上这个Token即可。

具体步骤如下:

  1. Provider通过TLS向APNs发起请求。
  2. APNs返回一个证书给Provider。
  3. Provier验证这个证书。通过后,发送push数据并带上JWT token。
  4. APNs验证token,并返回请求的结果。
Establishing and using token-based connection trust between a provider and APNs
Establishing and using token-based connection trust between a provider and APNs

建立TLS连接必须要有一个GeoTrust Global CA root certificate,在macOS中,这个证书已经安装在keychain中,如果是其他操作系统则可以在GeoTrust Root Certificates website下载。

2、Provider Authentication Tokens

关于JWT(JSON Web Token)的详细资料可以通过这里了解。同时也可以从这里找到一些现成可用的库。

下面对JWT进行详细的介绍,一个JWT实际上是一个JSON对象,它的头部必须包含:

  • 用以加密token的加密算法(alg) ,比如:ES256。
  • 10个字符长度的标识符(kid),(登入苹果开发者账号后,进入到Certificates, Identifiers & Profiles,然后点击APNs Auth Key,最后在右侧找到Apple Push Notification Authentication Key (Sandbox & Production)选项,点击创建后可以创建一个p8文件。)

同时他的claims payload部分必须包含:

  • issuer(iss) registered claim key,其值就是10个字符长的Team ID。
  • issued at (iat) registered claim key,其值是一个秒级的UTC时间戳。

比如:

{
    "alg": "ES256",
    "kid": "ABC123DEFG"
}
{
    "iss": "DEF123GHIJ",
    "iat": 1437179036
 }

创建完这个token后,必须使用自己的私钥对其进行加密,然后再采用基于P-256曲线和SHA-256哈希算法的椭圆曲线数字签名算法(ECDSA)进行签名,并将alg键的值设置为ES256。(注意:APNs只支持ES256签名的JWT,否则会返回InvalidProviderToken(403)错误)

为了保证安全,APNs要求定期更新token,时间间隔为1小时,如果APNs发现当前的时间戳与iat值中的时间戳相比,大于一个小时,那么APNs会拒绝推送消息,并返回ExpiredProviderToken (403)错误。

基于证书的方式(Certificate-based connection trust)

流程概述

这种方式是指Provider可以采用一个唯一的证书以及一个加密的私钥来与APNs交互,其中证书是由苹果产生的(通过苹果账号登录到developer account配置创建)。整个交互过程如下:

  1. Provider通过TLS向APNs请求连接。
  2. APNs向Provider返回一个APNs证书。
  3. Provider验证这个APNs证书,并将从苹果官网获取的证书返回给APNs。
  4. APNs验证通过后,这个链接就算是建立了。
Establishing certificate-based connection trust between a provider and APNs
Establishing certificate-based connection trust between a provider and APNs

APNs Provider Certificates

创建步骤可以参考Configure push notifications中的Generate a universal APNs client SSL certificate章节。

三、APNs连接

连接的管理

苹果的两个APNs server分别为:

  • Development server: api.development.push.apple.com:443
  • Production server: api.push.apple.com:443

要与APNs交互要求server必须支持1.2及上版本的TLS协议。通过上面的介绍我们已经知道,server跟APNs交互有两种方式:基于JWT的方式以及基于证书的方式。为了保证高质量的使用APNs应该注意如下几点:

  • 对于基于JWT的方式,应该定时更新token,token的有效期为1小时。
  • 对于基于JWT的方式,能每次请求都创建新的token,尽量在一小时内使用同一个token。
  • 不能频繁的建立、关闭连接,否则APNs会把这当做是黑客攻击,拒绝访问。应该尽量将连接保活,直到你认为这个连接接下来会长时间不使用为止。
  • 当需要发送大量的推送数据的时候,可以同时创建多个连接,以改善性能。
  • 当吊销证书或者token时,应该关闭所有相关的连接。

HTTP/2的请求与响应

详情可参见苹果官方文档HTTP/2 Request to APNs。这里介绍了接口的请求参数返回结果错误码以及示例代码。下面仅截取了其中的例子,以加深对APNs的使用的理解:

  • 基于证书的方式的request:

    HEADERS
      - END_STREAM
      + END_HEADERS
      :method = POST
      :scheme = https
      :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
      host = api.development.push.apple.com
      apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b //可以不填,如果不填APNs会自己创建一个UUID并在response中返回
      apns-expiration = 0
      apns-priority = 10
    DATA
      + END_STREAM
        { "aps" : { "alert" : "Hello" } }
    
  • 基于token方式的request:

    HEADERS
      - END_STREAM
      + END_HEADERS
      :method = POST
      :scheme = https
      :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
      host = api.development.push.apple.com
      authorization = bearer eyAia2lkIjogIjhZTDNHM1JSWDciIH0.eyAiaXNzIjogIkM4Nk5WOUpYM0QiLCAiaWF0I
     jogIjE0NTkxNDM1ODA2NTAiIH0.MEYCIQDzqyahmH1rz1s-LFNkylXEa2lZ_aOCX4daxxTZkVEGzwIhALvkClnx5m5eAT6
     Lxw7LZtEQcH6JENhJTMArwLf3sXwi
      apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
      apns-expiration = 0
      apns-priority = 10
      apns-topic = <MyAppTopic>
    DATA
      + END_STREAM
        { "aps" : { "alert" : "Hello" } }
    
    
  • 失败后的response:

    HEADERS
      - END_STREAM
      + END_HEADERS
      :status = 400
      content-type = application/json
        apns-id: <a_UUID>
    DATA
      + END_STREAM
      { "reason" : "BadDeviceToken" }
    
  • 成功后的response:

    HEADERS
      - END_STREAM
      + END_HEADERS
        apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
        :status = 200
    

四、设备token的生成与分发

在app启动的时候,必须向iOS系统注册远程推送,成功后,苹果将会返回一个设备token给app,此时app就可以将这个token上报给自己的后台。

如果有必要产生一个新的token,APNs会使用设备证书生成一个token(其中包含了一个设备ID),并使用token key加密后返回给设备。同时设备会将这个token以NSData对象的形式返回给app,app获取到该token之后应该将其发送到自己后台,后台之后就可以通过这个token来发送推送数据。过程如下图:

Managing the device token
Managing the device token

最后

通过苹果的官方文档我们可以知道provider与APNs的交互过程中,需要注意一下几点:

  • 推荐使用HTTP/2协议。
  • 必须加入TLS层。
  • 基于JWT的方式,token的最大有效期为1小时,并且不能频繁更换token。
  • 不能频繁创建、关闭连接,应该尽量少开连接,如果过于频繁,APNs将把其当做是黑客攻击,但是如果数据量大,可以同时多个连接向APNs发送消息。
  • 吊销token或者证书的时候,应该及时关闭老的连接。

参考文献

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

推荐阅读更多精彩内容