1. 程式人生 > >一步一步教你做ios推送 pem證書製作 php推送

一步一步教你做ios推送 pem證書製作 php推送

 最近在研究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檔案的同時,會在鑰匙串訪問中生成一對祕鑰,名稱為剛才我們填寫的常用名

二 下載開發證書和釋出證書

(這裡我為了大家能看清楚,已經把之前的證書事先吊銷了)

進入下一級頁面後在左側選擇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、多注意一下紅色字型部分 

在此感謝曾經為此而努力過的前輩們,尤其是感謝楊大哥的幫助。

另外附上幾個關於推送的不錯的帖子:

一篇很不錯的帖子,老外寫的

中文翻譯

在過程中如果有疑問可以新浪或騰訊微博@showhilllee雖然本人是菜鳥一個,也許不能為你把問題解決掉,但是會本著菜鳥精神去幫你解決

本文若有問題,歡迎大家斧正