转:http://blog.csdn.net/showhilllee/article/details/8631734

APNS的推送机制

首先我们看一下苹果官方给出的对ios推送机制的解释。如下图

Provider就是我们自己程序的后台服务器,APNS是Apple Push Notification Service的缩写,也就是苹果的推送服务器。

上图可以分为三个阶段:

第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。

第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。

第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。

APNS推送通知的详细工作流程

下面这张图是说明APNS推送通知的详细工作流程:

根据图片我们可以概括一下:

1、应用程序注册APNS消息推送。

2、iOS从APNS Server获取devicetoken,应用程序接收device token。

3、应用程序将device token发送给程序的PUSH服务端程序。

4、服务端程序向APNS服务发送消息。

5、APNS服务将消息发送给iPhone应用程序。

准备工作

首先要有一台苹果的设备,模拟器是不支持推送的,所以你需要一台iphone,ipod touch或者ipad。

我们的客户端与苹果服务器之间和我们自己的服务器与苹果服务器之间都需要证书来进行链接。下面我们来开始进入证书的制作过程。

一 CSR文件

首先我们要有生成一个Certificate Signing Request(也就是CSR)的请求文件。

在应用程序里的使用工具中找到钥匙串访问。

选择从证书颁发机构请求证书

填上你的邮箱和常用名,常用名要记一下,一会会用到。然后选择保存到磁盘,继续

保存位置在桌面,点击存储。

到这里点击完成后我们会在桌面上看到一个CertificateSigningRequest.certSigningRequest的请求文件,也就是我们说的CSR文件。在我们生成CSR文件的同时,会在钥匙串访问中生成一对秘钥,名称为刚才我们填写的常用名

二 下载开发证书和发布证书

(这里我为了大家能看清楚,已经把之前的证书事先吊销了)

https://developer.apple.com/devcenter/ios/index.action登录后,在右侧的ios Developer Program里点击iOS Provisioning Portal。

进入下一级页面后在左侧选择Certificates

点击红色的部分生成一个开发证书

点击选择文件,选择刚才我们生成到桌面的CSR请求文件。

注意,如果你在后面测试的时候出现了问题,请检查一下这里,这里的CSR请求文件必须是我们刚才生成的那个

选择完成后点击Submit提交

提交完成后返回页面。页面会是这样的,然后我们刷新一下页面

刷新后会出现一个下载按钮,我们点击下载。现在我们的开发证书已经配置并下载好了,发布证书的配置过程和开发证书是一致的,不再赘述。下载完后双击,会跳到钥匙串访问里。这就是我们之后要进行测的证书

三 配置AppID,配置并下载SSL证书

点击左侧的App IDs,找到我们要做推送功能的程序的id(如果没有的话要先New一个。注意,这里的App ID必须不能是通配的,通配的不可以做推送)。点击Configure

进入后默认推送功能是关闭的,我们需要把推送功能打开

选中打开后,点击右边灰色的Configure按钮

这里的文件同样的,还是选择我们生成在桌面上的CSR请求文件

然后点击继续

出现了我们需要的SSL证书,我们点击下载后点击Done完成。

Status状态变成了绿色可用了。这里右边的下载和上一步的下载是一样的,如果在上一步中下载了证书,便无需再次下载。此时我们有了一个名字叫aps_development.cer的SSL证书,同样,我们把他放在桌面。双击后会跳到钥匙串访问,出现我们的SSL推送证书

同样的,发布的SSL证书的步骤也是一样的。

四 下载Provisioning证书

在左侧选择Provisioning

配置好后点击提交(注意App ID要与我们刚的程序对应)

之后变回出现下载按钮,我们点击下载。下载后双击,并将我们的设备上的描述文件更新一下(最好把之前的全部删除,然后再安装,防止出错)。

五 从钥匙串访问中导出秘钥

打开钥匙串访问,找到我们的专用秘钥(专用秘钥的名称就是我们在最开始生成CSR请求的时候填写的常用名)

右键选择导出

导出的文件名我们叫做Push

在这里需要输入一个密码来对文件进行加密。这里我们选择abcabc,当然你也可以自己选择是什么,但是这个密码必须要铭记,切记!

然后输入你电脑的密码,点击允许。

这样我们就在桌面上生成了一个Push.p12文件。

到此为止,我们在桌面上一共生成了三个文件。一个是CSR请求文件,一个是aps_development .cer的SSL证书文件,还有一个刚才生成的Push.p12秘钥文件。

现在我们的准备工作已经做完了。要开始对生成的文件进行处理了。原因上面已经解释过,因为我们的服务链接苹果服务器也是需要证书的,但是我们直接生成的证书windows系统(我们一般的服务器都是win系统的)是不识别的,所以我们需要生成一个后缀为pem的带证书带秘钥的文件。

六 处理证书

下面我们打开终端(位置:应用程序à实用工具à终端)。

cd到桌面,我们那三个文件所在的位置

1、把.cer的SSL证书转换为.pem文件,执行命令:

openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem

在桌面上会生成一个PushChatCert.pem文件


 

2、把私钥Push.p12文件转化为.pem文件:

openssl pkcs12 -nocerts -out PushChatKey.pem -in Push.p12

这里需要我们输入密码,这个密码也就是我们导出p12文件时的密码,也就是我们上面设置的abcabc。然后,需要我们对生成的pem文件设置一个密语,这里我们推荐还是用上面这个abcabc,防止混乱(当然你也可以设置成别的更有意义的密语),这里的密语是要告诉我们服务器的。这样,桌面上又会生成一个PushChatKey.pem文件

3、对生成的这两个pem文件再生成一个pem文件,来把证书和私钥整合到一个文件里:

cat PushChatCert.pem PushChatKey.pem > ck.pem

生成ck.pem文件

这样,我们的文件就制作完了。下面进入测试阶段

为了测试证书是否工作,执行下面的命令

telnet gateway.sandbox.push.apple.com 2195

它将尝试发送一个规则的,不加密的连接到APNS服务。如果你看到上面的反馈,那说明你的MAC能够到达APNS。按下Ctrl+C关闭连接。如果得到一个错误信息,那么你需要确保你的防火墙允许2195端口。一般这里都不会出现什么问题。

下面我们要使用我们生成的SSL证书和私钥来设置一个安全的链接去链接苹果服务器:

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem

执行完这一句命令后需要我们输入密语

Enter pass phrase for PushChatKey.pem:

我们输入abcabc按回车

你会看到一个完整的输出,让你明白OpenSSL在后台做什么。如果链接是成功的,你可以随便输入一个字符,按下回车,服务器就会断开链接,如果建立连接时有问题,OpenSSL会给你返回一个错误信息。

当你在最后的时候你看到这样说明你已经成功了:

CONNECTED(00000003)

depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa isincorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust CertificationAuthority - L1C

verify error:num=20:unable to get local issuercertificate

verify return:0

---

Certificate chain

0s:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=iTMSEngineering/CN=gateway.sandbox.push.apple.com

i:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated byreference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C

1s:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated byreference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C

i:/O=Entrust.net/OU=www.entrust.net/CPS_2048incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.netCertification Authority (2048)

---

Server certificate

-----BEGIN CERTIFICATE-----

MIIFGzCCBAOgAwIBAgIETBz90jANBgkqhkiG9w0BAQUFADCBsTELMAkGA1UEBhMC

……省略……

fMGbLqkGn8YogdPqe5T1

-----END CERTIFICATE-----

subject=/C=US/ST=California/L=Cupertino/O=AppleInc./OU=iTMS Engineering/CN=gateway.sandbox.push.apple.com

issuer=/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa isincorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust CertificationAuthority - L1C

---

No client certificate CA names sent

---

SSL handshake has read 2731 bytes and written 2165 bytes

---

New, TLSv1/SSLv3, Cipher is AES256-SHA

Server public key is 2048 bit

Secure Renegotiation IS supported

Compression: NONE

Expansion: NONE

SSL-Session:

Protocol  : TLSv1

Cipher    : AES256-SHA

Session-ID:

Session-ID-ctx:

Master-Key:C7A47EED5E1F5……省略……369D4

Key-Arg   : None

Start Time:1361862882

Timeout   : 300 (sec)

Verify return code: 0 (ok)

---

在这里提醒一下,也许你会看到像我这样的提示:verify error:num=20:unable to get local issuercertificate

verify return:0

其实是没问题的。

七 项目测试

建立我们的推送的项目(注意BundleIdentifier必须和我们推送应用的App id一致)

在AppDelegate里didFinishLaunchingWithOptions函数里写

- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

……

//推送的形式:标记,声音,提示

[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];

return YES;

}

- (void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {

NSLog(@"regisger success:%@",pToken);

//注册成功,将deviceToken保存到应用服务器数据库中

}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{

// 处理推送消息

NSLog(@"userinfo:%@",userInfo);

NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);

}

- (void)application:(UIApplication *)applicationdidFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

NSLog(@"Registfail%@",error);

}

我们运行程序的时候会有提示,说我们的程序要发送推送通知

下面我们把php服务器代码和生成的ck.pem文件放在统一文件夹下面(这里我们还是统一放在桌面上)。

用Xcode打开(其他工具也可以)php服务器端的代码,把deviceToken改成我们现在要进行测试的iphone的deviceToken(获得方法:首先运行我们的程序,程序启动后打印的日志文件里可以看到。感谢 边玩勺子把儿去 同学的提醒),密语改成我们之前设置的abcabc。然后保存。

然后在终端运行命令(如果刚才你关闭了终端的话,最好ls一下,看看当前是不是在桌面),执行命令:

php pushMe.php

然后回车(pushMe为服务器文件名称)

如果出现这样的提示说明成功了,然后在iphone上,我们期待已久的推送消息终于来了。

以下是推送的几种效果:

常见问题:

1、在用证书和秘钥链接服务器时出现提示:

Error opening client certificate private key filePushChatKey.pem

20839:error:02001002:system library:fopen:No such file ordirectory:/SourceCache/OpenSSL098/OpenSSL098-44/src/crypto/bio/bss_file.c:356:fopen('PushChatKey.pem','r')

20839:error:20074002:BIO routines:FILE_CTRL:systemlib:/SourceCache/OpenSSL098/OpenSSL098-44/src/crypto/bio/bss_file.c:358:

unable to load client certificate private key file

解决:

文件路径不对。cd到生成的pem文件路径下再进行链接

2、前期测试没有问题,将ck.pem给服务器,通过服务器进行推送时推送不成功,提示链接APNS失败。

解决:一,看一下证书的名称,密语是否正确;二,路径是否正确;然后检查一下库,OpenSSL和libssl;此外apache还要开启OpenSSL权限,确保可以访问pem

3、APNS地址 
测试地址gateway.sandbox.push.apple.com:2195 
发布地址 gateway.push.apple.com:2195

测试的地址用的是沙盒,发布地址是不同的。发布软件的时候记得改过来

4、要注意顺序问题,一定要按照这个顺序来:

生成钥匙串请求 -->配置下载开发证书-->  配置App ID ,配置、下载SSL证书-->Provisioning证书

5、多注意一下红色字体部分

在此感谢曾经为此而努力过的前辈们,尤其是感谢杨大哥的帮助。

在这里附上杨大哥的帖子:http://www.cocoachina.com/bbs/read.php?tid=102110&page=1

另外附上几个关于推送的不错的帖子:

http://zxs19861202.iteye.com/blog/1532460

一篇很不错的帖子,老外写的

http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12

中文翻译

http://article.ityran.com/archives/194

在过程中如果有疑问可以新浪或腾讯微博@showhilllee虽然本人是菜鸟一个,也许不能为你把问题解决掉,但是会本着菜鸟精神去帮你解决

转帖请注明出处:http://blog.csdn.net/showhilllee/article/details/8631734

php服务器代码pushMe.php:http://vdisk.weibo.com/s/zw-xeocHvZSgv

[转]ios push的更多相关文章

  1. 苹果推送(APNs)ios push小结

    把app删除后就推送不成功了,可以看出deviceToken应该是设备+app来一起识别的,重新安装后仍然为同一个 简介 推送服务APNs(Apple Push Notification servic ...

  2. iOS push过去的时候界面不能完全退出

    iOS push过去的时候界面不能完全退出 解决方法:设置self.view.backgroundcolor 1. initWithFrame方法是什么?  initWithFrame方法用来初始化并 ...

  3. IOS PUSH 实践操作~~~~

    1.推送过程简介        (1)App启动过程中,使用UIApplication::registerForRemoteNotificationTypes函数与苹果的APNS服务器通信,发出注册远 ...

  4. iOS push全方位解析(二)【译文】"——生成OpenSSL证书,Provisioning Profile

    这是一篇来自raywenderlich的教程,内容翔实!结构简单透彻.讲解循序渐进.文章质量上乘!是一篇难的的博文!使用半瓶的英语水平翻译了一下: 1.[iOS push全方位解析](一) push的 ...

  5. iOS Push详述,了解一下?

    WeTest 导读 本文主要对iOS Push的在线push.本地push及离线(远程)push进行梳理,介绍了相关逻辑,测试时要注意的要点以及相关工具.小小的Push背后蕴藏着大大的逻辑! Push ...

  6. 了解iOS消息推送一文就够:史上最全iOS Push技术详解

    本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...

  7. iOS - Push 通知推送

    1.UserNotifications 通知是 App 用来和用户交流的一种方式,特别是当 App 并没有在前台运行的时候.通知,正如它的名称所强调的,被用作向用户'通知'一个事件,或者仅仅向用户提示 ...

  8. IOS PUSH

    第一阶段:.net应用程序把要发送的消息.目的iPhone的标识打包,发给APNS. 第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPh ...

  9. (转)pem, cer, p12 and the pains of iOS Push Notifications encryption

    转自:http://cloudfields.net/blog/ios-push-notifications-encryption/ The serious pains of setting up a ...

随机推荐

  1. Java 中使用javah编译头文件出现找不到类的情况

    在工程的bin目录下,输入命令: javah -classpath . -jni 类路径.JNI类

  2. python之路:Day01 --- Python基础1

    本节内容 1.Python介绍 2.发展史 3.变量 4.用户输入 5.表达式 if...else语句 6.表达式 for 循环 7.表达式 while 循环 8.模块初识 9.数据类型初识 10.数 ...

  3. Enterprise Achitect使用与类的关系的简单介绍

    本文作为Enterprise Achitect初步使用,另外也是类图基本介绍,是设计模式的基础.  类的关系有泛化(Generalization).实现(Realization).依赖(Depende ...

  4. 【Java EE 学习 77 上】【数据采集系统第九天】【通过AOP实现日志管理】【通过Spring石英调度动态生成日志表】【日志分表和查询】

    一.需求分析 日志数据在很多行业中都是非常敏感的数据,它们不能删除只能保存和查看,这样日志表就会越来越大,我们不可能永远让它无限制的增长下去,必须采取一种手段将数据分散开来.假设现在整个数据库需要保存 ...

  5. Python-面向对象

    面向过程变成:函数式变成,C程序等 面向对象编程:C++,Java,Python等   类和对象: 类:是对事物的抽象,比如人类.球类 对象:是类的一个实例,比如足球.篮球   实例说明: 球类可以对 ...

  6. WebGL入门教程(四)-webgl颜色

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 颜色效果图: 操作步骤: 1.创建HTML5 canva ...

  7. PDA手持扫描资产标签,盘点完成后将数据上传到PC端,固定资产系统查看盘点结果

    固定资产管理系统介绍: 致力于研发条码技术.集成条码系统的专业性公司,针对客户的不同需求,提供一站式的企业条码系统解决方案:包括功能强大的软件系统.安全可靠的无线网络.坚固耐用的硬件系统.灵活易用的管 ...

  8. mybatis多表查询

    1.在类的属性里定义另一个关联类,在mapper.xml里写result-mapper加association 2.表很多的话,可以在数据库里建视图view,把不同表里需要的字段写到一张视图里 写po ...

  9. install hdp 2.2 on ubuntu 14.04

    http://www.swiss-scalability.com/2014/12/install-hdp-22-on-ubuntu-1404-trusty.html 在新加节点上运行 sed -e & ...

  10. CustomUI Direct3D9_Sample

    刚开始建这个项目的时候编译器报了很多Link2019的错误. 后来添加了一些lib文件才解决,参考    缺少.lib文件导致的Link2019 解决方案汇总 ==================== ...