最新消息:iOS编程开发交流群(6906921) ,Mac.Cocoa开发交流群(7758675) 欢迎iOS/macOS开发编程爱好及学习者加入!

基于HTTP/2与Token的APNs新协议

iOS 天狐 48111浏览 5评论

新的APNs协议基于HTTP/2,一种是使用Universal Push Notification Client SSL 证书,一种是使用Token,本文主要讲基于token的APNs协议。

基于HTTP/2与Token的 APNs 协议

APNs Provider(即,APP的后台) API 允许您向您的 iOS,macOS 设备上的应用程序和 Apple Watch 发送远程通知。API 基于 HTTP/2 网络协议。每个交互通过一个 POST 请求,包含 JSON 的有效Payload负载,通过服务器使用Auth Key生成服务端token连接APNs服务器,并且通过设备token发送负载。APNs然后转发给特定设备的指定应用程序。

  •  Request 和 Response 使用JSON通信
  • APNs支持状态码和返回 error 信息
  • APNs推送成功时 Response 将返回状态码200
  • APNs推送失败时,Response 将返回 JSON 格式的 Error 信息。
  • 最大推送长度提升到4096字节(4Kb)
  • 可以通过 “HTTP/2 PING ” 心跳包功能检测当前 APNs 连接是否可用,并能维持当前长连接。
  • 支持为不同的APP定义 “topic”(其实就是App Bundle ID)
  • 多个推送App,只需要一个Apple Push APNs Auth Key

Apple Push Notification Authentication Key

2016年9月,苹果悄悄上线了token验证的推送方式,通过获得一个认证密钥(APNs Auth Key)去生成服务器端token,并且token非常容易生成,可以使用这些token令牌代替推送证书。一个认证密钥可用于多个应用程序并且永远不过期。每一个需要推送的App都需要配置推送证书的时代过去了。but,大部分第三方推送服务商,目前都没有升级到APNs Auth Key Token模式。

Auth key 生成

开发者网站证书页面:https://developer.apple.com/account/ios/certificate/key

选择Apple Push Notification Authentication Key (Sandbox & Production)并且点击页面底部的Continue

网站会生成包含APNs Auth Key的.p8密钥文件,下载下来APNsAuthKey_xxxxxxx.p8后续连接APNS使用。

协议说明

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

具体步骤如下:

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

重要:

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

HTTP/2请求APNs

HTTP/2 请求字段
字段名 字段值
:method POST
:path /3/device/<device-token>

对于 <device-token> 参数,指定目标设备的十六进制字节。

APNs需要使用 HPACK (HTTP/2 的报头压缩),防止重复的标题键和值。APNs为HPACK维护一个小的动态表。为了避免填满了APNs HPACK表,因而必须丢弃表数据,编码headers以下列方式 — — 尤其是当发送大量的流︰

:method 必须为POST

:path 值应编码为一个header中的一个文本字段,没有索引

authorization 请求header,如果存在,应编码为一个header中的一个文本字段,没有索引

apns-id、 apns-expiration,和 apns-collapse-id 不同的编码取决于它是否是第一次初始请求或随后的 POST 操作的一部分,如下︰

第一次发送请求头的时,使增量索引编码允许头名称加入动态表中

子请求发送头时,编码成header中的一个文本字段,没有索引

请求头

APNs 请求头 http headers
Header 头 描述
authorization 提供的发送到指定(app)主题通知的APNs验证token,token是以Base64 URL编码的JWT格式。指定为bearer <provider token>

当使用证书连接的时候,这个请求头将会被忽略

apns-id 一个规范的的 UUID 用来标识通知。如果发送通知时发生错误,APNs 使用此值来标识通知,通知到您的服务器。

规范的格式是 32 个小写的十六进制数字,由连字符分隔为5,8-4-4-4-12。UUID一个例子如下:

123e4567-e89b-12d3-a456-42665544000

如果您省略这个头,一个新的UUID由APNs创建并且在response中返回

apns-expiration 通知过期时间,秒级的UTC时间戳,这个header标识通知 从何时起不再有效,可以丢弃。

如果这个值非零,APNs保存通知并且尽量至少送达一次。如果无法第一时间送达,根据需要重复尝试。

如果这个值为0,APNs认为通知立即过期,不会存储与重新推送。

apns-priority 通知的优先级,指定以下值:

  • 10–立即推送消息. 这个优先级的通知必须再目标设备上触发alert, 声音, 或者badge . 仅仅包含content-available key使用此优先级是错误的。
  • 5—一次性发送通知,需要考虑设备的电量。具有此优先级的通知可能分组推送并且几种爆发推送  Notifications with this priority might be grouped and delivered他们会被节流并且某些情况下送达

如果省略这个头,APNs服务器会把优先级设置为10

apns-topic 远程通知的主题,通常是你App的bundle id,在开发者账号中创建的证书必须包含此bundle id

如果证书包含多个主题,这个头必须指定一个值

如果省略此头并且APNs证书不包含指定的主题,APNs服务器使用证书的Subject作为默认主题。

如果使用token代替证书,必须指定此头,提供的主题应该被在开发者账号中的team提供。即bundle id的app应该与auth key同属于一个开发者组。

apns-collapse-id 具有相同的折叠标识符的多个通知推送给用户合并显示为单个通知。比如: apns-collapse-id : 2 ,那么value为2的消息将被APNS合并成一条消息推送给设备。此关键字的值不能超过 64 个字节。更多的信息,请参阅Quality of Service, Store-and-Forward, and Coalesced Notifications

Provider Authentication Tokens

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

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

  • 用以加密token的加密算法(alg) ,比如:ES256。
  • 10个字符长度的标识符(kid),(苹果开发者网站创建的APNs Auth Key详情中的key id)

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

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

比如:

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

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

请求体

body内容是将要推送的消息负载的JSON对象。body数据必须压缩最大大小 4 KB (4096 字节)。对于 (VoIP) 通知,body数据最大大小 5 KB (5120 字节)。
有关负载中的具体请参阅Payload Key Reference

响应头

APNs 响应头 response headers
Header 名 Header值
apns-id apns-id从request得到, 如果request中没有此值, APNs服务器创建一个新的UUID并且在header中返回
:status HTTP状态码,HTTP status code.可能status codes, 参加下文

响应状态码

Status codes for an APNs response
Status code Description
200 成功
400 无效请求
403 证书错误或者验证token错误
405 :method 设置错误. 只支持 POST 请求
410 device token不在有效与topic
413 负载payload太大
429 服务端对于同一个device token发送了太多了请求
500 内部服务器错误
503 服务器关闭,不可用

使用

Sample request for a provider authentication token

APNs Auth Key 与 shell

后续更新其他语言推送方法。

参考资料

CommunicatingwithAPNs

http://thrysoee.dk/apns/

 

 

转载请注明:天狐博客 » 基于HTTP/2与Token的APNs新协议

微信 OR 支付宝 扫描二维码
为天狐 打赏
非常感谢你的支持,哥会继续努力!
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (5)

  1. 你好!可不可把你那个p8文件发给我, 运行测试一下这个脚本呢?目前我们这个证书还没有申请下来。
    lang8年前 (2017-06-02)回复
    • 这。。。。。
      天狐8年前 (2017-06-06)回复
  2. 哈哈,真有趣
    dd7年前 (2017-09-12)回复
  3. 他那个p8生成的token和P12的那个token有什么区别,p8的要针对做什么处理吗
    大佬6年前 (2018-09-14)回复
  4. 有没有java的demo
    大佬6年前 (2018-09-14)回复