最近在研究ios的推送问题,遇到了一些问题,最终整理了一下。放在这里和大家分享

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(获得方法,:在Xcode的顶部工具栏点击windowàOrganizer,在左侧选中我们的iphone后,右边的Identifier后面的就是了),密语改成我们之前设置的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推送的更多相关文章

  1. 转载:手把手教你做iOS推送

    手把手教你做iOS推送 http://www.cocoachina.com/industry/20130321/5862.html

  2. IOS 推送消息 php做推送服务端

    IOS推送消息是许多IOS应用都具备的功能,最近也在研究这个功能,参考了很多资料终于搞定了,下面就把步骤拿出来分享下: iOS消息推送的工作机制可以简单的用下图来概括: Provider是指某个iPh ...

  3. C# 服务端推送,十步十分钟,从注册到推送成功

    目标 展示 C# 服务端集成极光推送的步骤,多图少字,有图有真相. 使用极光推送, C# 服务端推送到 Demo App,Android 手机收到推送,整理为十个步骤,使用十分钟左右,完成从注册账号到 ...

  4. 手把手教你搞定个推iOS推送SDK集成

    以下是一位开发者在集成个推iOS推送SDK过程中的真实经历. 作者:Ezreallp 一次偶然的机会,公司的项目要用到推送,我自己本来就很懒,不愿意去弄整套APNS的流程,刚好之前跟朋友聊起过他们的产 ...

  5. 友盟iOS推送配置(从真机调试到推送)

    下面我来讲解一下友盟iOS的推送配置,其实友盟只是一个示例,换做其余的第三方推送服务也会适用,只是第三方的后面服务变了而已. iOS推送(包括真机调试)所需要的步骤和文件如下: 备注:这里我将省略掉一 ...

  6. “iOS 推送通知”详解:从创建到设置到运行

    这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了视频讲解.本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义. 介绍一点点背景资料 ...

  7. iOS推送 再备

    这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了视频讲解.本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义. 介绍一点点背景资料 ...

  8. iOS 推送全解析

    本文旨在对 iOS 推送(以下简称 推送)进行一个完整的剖析,如果你之前对推送一无所知,那么在你认真地阅读了全文后必将变成一个推送老手,你将会对其中的各种细节和原理有充分的理解.以下是 pikacod ...

  9. iOS 推送全解析,你不可不知的所有 Tips!

    本文旨在对 iOS 推送进行一个完整的剖析,如果你之前对推送一无所知,那么在你认真地阅读了全文后必将变成一个推送老手,你将会对其中的各种细节和原理有充分的理解.以下是 pikacode 使用 iOS ...

随机推荐

  1. spring aop切面配置

    <bean id="aopLog" class="sardine.commodity.biz.AopLog"/>    <aop:config ...

  2. (转)jquery的html,text,val

    .html()用为读取和修改元素的HTML标签 .text()用来读取或修改元素的纯文本内容 .val()用来读取或修改表单元素的value值. 这三个方法功能上的对比 .html(),.text() ...

  3. DNN - Modules - QR Code Generator

    Dotnetnuke 平台上的二维码模块.支持DNN 7.x平台的安装 QR码(快速响应码)是二维条形码.随着移动设备市场正以快速的步伐,QR码正在成为非常重要的营销工具.与移动电话或平板电脑的扫描, ...

  4. 遍历页面上所有TextBox,并赋值为String.Empty

    //不含母板页 foreach (System.Web.UI.Control txtobj in this.Page.Controls)   {     if (txtobj.GetType().Na ...

  5. ImageView的学习

    学习安卓时我还是习惯看懂手册,虽然是英文但是可以获得的东西必然也是更多的,否则自己只能停留在拾人牙缝的水平,虽然我是初学,但是还是分享一些自己的学习过程及方法. 从手册中我们看以知道,ImageVie ...

  6. 武汉科技大学ACM:1004: 华科版C语言程序设计教程(第二版)习题5.6

    Problem Description 这天老师又给小豪出了一道题目:给你三根长度分别为a,b,c的火柴,让你计算这三跟火柴能组成的三角形的面积. Input 输入每行包括三个数a,b,c. Outp ...

  7. javascript触发input-file的click事件

    概述 input:file本身自带的样式不太好看,但是又没法设置样式. 由于系统限制,不能通过代码触发,只允许用户自主点击. 通常的解决办法是,把input:file透明化,实际上点击的还是input ...

  8. 【行为型】Chain of responsibility模式

    职责链模式将对象的请求处理组成链式结构,并将请求按链式结构逐个传递下去,直接被其中的某个处理者处理为止.由此可知,职责链模式的适用场合是对指定请求,可以有多个请求处理者(或称为请求响应者),但用户并不 ...

  9. php批量上传图片并把图片名放入数据库

    前几天工作中要做这样一个功能,有八百多个系统 生成的会员:给这八百多个系统会员上传图片:然后把图片名放入数据库. 第一步: 第一步肯定是首先把图片上传到对应的图片目录下,直接用框架中已经有的上传类: ...

  10. 对PHP安全有帮助的一些函数

    安全一直是一个在编程语言中非常值得去关注的方面.在任何一种成熟的编程语言中都有合适的办法来保证程序的安全性,在现代的 WEB 开发中 安全一直是一个在编程语言中非常值得去关注的方面.在任何一种成熟的编 ...