【Android】GCM restricted_package_name的作用?

前言

      在做GCM推送的时候,遇到GCM Server返回“Invalid Package Name”的错误信息。一开始以为是服务端的Server API Key与APP没有匹配上,后来查明是后台人员在发往GCM Server的消息中加了restricted_package_name这个字段,并且传了错误的值。于是引发了以下对restricted_package_name字段的探究。

restricted_package_name的含义

官网是这样解释的:

This parameter specifies the package name of the application where the registration tokens must match in order to receive the message.

即是说,只有restricted_package_name字段中指定包名的应用才能接收到推往设备的消息。

restricted_package_name的验证

      于是,我们尝试在推送消息中加入restricted_package_name字段,并赋以不同的value进行测试,得到如下结论:

     * 正确的包名,推送成功。

     * 空字符串,推送成功。

     * 错误的包名,推送失败。返回“Invalid Package Name”错误信息。

      由以上的测试,可以看出:只要restricted_package_name予以有效赋值,GCM Server就会发往指定包名的应用。但是,如果推送的registration ids并不是为该应用分配的,则会报“Invalid Package Name”,信息不会被发送。

restricted_package_name是否必要?

首先我们先来理一下推送流程:

1.在GCM官网创建应用Create or choose an app。我们填写APP packagename,由此生成Server API Key以及APP SenderId。

2.APP通过SenderId,获取registration id(类似iOS的deviceToken),并发给Server。

3.Server通过API Key发送消息到registration id标识的设备上的APP。

      从流程中,可以看到API Key、SenderId、registration id是相互关联的。并且,我们似乎可以猜测,GCM Server收到推送请求时能够判断API Key与registration id是否匹配,并且是发往哪一个应用的。

      为什么说能识别出发往哪一个应用?这主要是出于两个方面:一是创建应用时需要填写packagename,通过API Key可以找出对应的packagename;二是registration id,官网写着“a token that can identify and authorize the instance of the application on the device.This is similar to an OAuth2 token except, it applies to the application instance instead of a user.”即它至少包含device和application两个信息,同样可以拿到packagename;而且从上文“Invalid Package Name”的错误信息也能说明registration id可以获取packagename。

      写到这里,估计大家都困惑了。既然GCM Server能通过API Key和registration id识别packagename,那restricted_package_name是不是显得有点多余?答案并非如此,我们只是说GCM Server可以通过API Key和registration id分别获取对应的packagename并校验其一致性,但不代表GCM Server有这样做!一切靠实际结果来验证。

      接下来,我们就来做一下测试:

前期准备:

* 一台安卓设备

* APP 1,对应Server 1、SenderId 1、API Key 1

* APP 2,对应Server 2、SenderId 2、API Key 2

* 不加restricted_package_name字段

测试案例 1:验证“GCM Server是否会校验API Key与registration id的一致性”

为了好理解一点,我们可以假设这样一个场景:4月1日想恶作剧一下,打算用我们的服务器往别人家APP推送一条搞怪的消息。

注意:在案例中registration id简称为token

测试过程:

1.APP 2通过SenderId 2生成一个token 22(22表示由APP 2利用SenderId 2生成的)。

2.Server 1拿到这个token 22,通过API Key 1推送消息到token 22。

测试结果:

GCM Server返回“MismatchSenderId”的错误信息。

测试案例 2:验证“GCM Server是否会校验API Key与registration id对应packagename的一致性”

同样,我们可以假设这样一个场景:一个黑客破解了我们APP的源码,拿到我们的SenderId,然后自己写一个APP利用这个SenderId生成对应token,并发给我们服务器注册,这样我们服务器推送消息时也会推给黑客的APP。

测试过程:

1.APP 2通过SenderId 1生成一个token 21(21表示由APP 2利用SenderId 1生成的);

2.Server 1拿到这个token 21,通过API Key 1推送消息到token 21。

测试结果:

Server 1推送成功,APP 2能够接收到推送消息。

测试案例 3:为了进一步验证,我们让Server 1同时往token 11、token21推送同一条消息,结果APP1、APP2都能接收到推送消息。

结论:

1.GCM Server会校验API Key与registration id的一致性。

2.GCM Server不会校验API Key与registration id对应APP packagename的一致性。

      以上,我们就可以明白了,只要“API Key”与“registration id对应的SenderId”能够匹配上,就可以推送成功。GCM Server并不管是哪一个应用!restricted_package_name的作用不言而喻。

>> 同样,我们对此进行了验证。

测试案例 4:在基于案例3的基础上,加入restricted_package_name。首先赋以APP 1的packagename,结果是:token 11(APP 1)推送成功,token 21(APP 2)报“Invalid Package Name”错误信息;其次改为APP 2的packagename,结果是:token 11(APP 1)报“Invalid Package Name”错误信息,token 21(APP 2)推送成功。

为什么GCM Server不校验?

这也不能说是Bug,可能是Google工程师觉得没有必要,也可能是GCM允许同个开发者的多个应用可以共享同一套API Key和SenderId吧。

questions about security nature of GCM这个帖子中,一位开发者提出了类似案例2中的场景,对此,Google工程师在答复中发布了“加入restricted_package_name字段”的消息,并且指出真正的问题--“为什么APP 2可以在Server 1上注册token?”他建议:向Server注册token时,应进行加密处理或者一定的校验,以保证token的合法性。

总结

GCM 同一套API Key和SenderId允许发给多个应用,可以通过restricted_package_name来指定某个应用。


参考文章

Implementing GCM Server

groups.google.com/forum/#!topic/android-gcm/M-EevBitbhQ

android - Why is restricted_package_name used? - Stack Overflow

developers.google.com/cloud-messaging/http-server-ref#error-codes

developers.google.com/android/reference/com/google/android/gms/iid/InstanceID.html#getToken(java.lang.String, java.lang.String)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,009评论 19 139
  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的阅读 13,562评论 5 6
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,638评论 25 708
  • 第一次知道奥黛丽赫本是因为电影《罗马假日》,是在2年前无意中赏析的一部经典。我震惊世间原来还存在过这样美丽,优雅的...
    海鸥老师阅读 1,214评论 8 29
  • 七夕,现在是国内的凌晨三点,美国的下午三点,探哥睡着了,我刚结束一段忙碌,刚才微信问他,如果我在国内,七夕节我们干...
    心念随笔阅读 314评论 0 1