1, JSPatch熱更新
眾所周知,AppStore 上發布需要有個一非常惡心的審核期,而且很可能被拒絕掉,發布或者迭代一個 App一般耗時是5-10個工作日.但是如果線上版本出現了一些問題,或者公司市場部突然要做某些活動,這就會讓 iOS 的程序員手忙腳亂.現在市場上很多大公司比如淘寶,58同城等都采用了 OC 和 HTML5 混編方法處理我說的那幾個問題, 這是現在最好的熱更新解決方案 ,但是 iOS 程序員去寫 H5有點不現實
2,為什么能熱更新,原理
能做到通過JS調用和改寫OC方法最根本的原因是 Objective-C 是動態語言,OC上所有方法的調用/類的生成都通過 Objective-C Runtime 在運行時進行,我們可以通過類名/方法名得到相應的類和方法,進一步用 js 的代碼來代替實現方法.
JSPatch用iOS內置的JavaScriptCore.framework作為JS引擎,但沒有用它JSExport的特性進行JS-OC函數互調,而是通過Objective-C Runtime,從JS傳遞要調用的類名函數名到Objective-C,再使用NSInvocation動態調用對應的OC方法。
3,優缺點
1>.JS語言
JS比Lua在應用開發領域有更廣泛的應用,目前前端開發和終端開發有融合的趨勢,作為擴展的腳本語言,JS是不二之選。
2>.符合Apple規則
JSPatch更符合Apple的規則。iOS Developer Program License Agreement里3.3.2提到不可動態下發可執行代碼,但通過蘋果JavaScriptCore.framework或WebKit執行的代碼除外,JS正是通過JavaScriptCore.framework執行的。
3>.小巧
使用系統內置的JavaScriptCore.framework,無需內嵌腳本引擎,體積小巧。
4>.支持block
wax在幾年前就停止了開發和維護,不支持Objective-C里block跟Lua程序的互傳,雖然一些第三方已經實現block,但使用時參數上也有比較多的限制。
風險
JSPatch讓腳本語言獲得調用所有原生OC方法的能力,不像web前端把能力局限在瀏覽器,使用上會有一些安全風險:
1>.若在網絡傳輸過程中下發明文JS,可能會被中間人篡改JS腳本,執行任意方法,盜取APP里的相關信息??梢詫鬏斶^程進行加密,或用直接使用https解決。
2>.若下載完后的JS保存在本地沒有加密,在未越獄的機器上用戶也可以手動替換或篡改腳本。這點危害沒有第一點大,因為操作者是手機擁有者,不存在APP內相關信息被盜用的風險。若要避免用戶修改代碼影響APP運行,可以選擇簡單的加密存儲。
4,如何使用
1,注冊賬號,以及app,會生成一個appkey
2,導入框架和依賴項和AppDelegate
在該平臺下載SDK解壓后將JSPatch.framework拖入項目
添加依賴框架libz.dylib和JavaScriptCore.framework
1中startWithAppKey傳入平臺申請的appKey,啟動JSPatch SDK,同時會自動執行已下載到本地的patch.
2中sync與JSPatch平臺后臺更新,詢問是否有patch更新,如果有更新會自動下載并執行。startWithAppKey并不會詢問后臺patch更新,必須調用sync方法。注意:**實時性不高的App只需在didFinishLaunchingWithOptions處調用一次,用戶啟動時就會同步patch信息;實時性要求高的App,在applicationDidBecomeActive處調用,用戶每次喚醒App時就同步一次后臺
在AppDelegate.m的didFinishLaunchingWithOptions中添加如下代碼:
//添加頭文件
#import <JSPatch/JSPatch.h>
//1
[JSPatch startWithAppKey:JSPatchKey] //JSPatchKey是創建App獲得的AppKey
//2
[JSPatch sync]
3,測試本地腳本
在上線之前需要對腳本進行本地測試查看運行是否正常,注意JSPatch平臺規范,JS腳本文件名必須是main.js。SDK提供了方法+testScriptInBundle用于發布前測試,調用該方法后,JSPatch會在當前項目的bundle尋找main.js。
注意:+testScriptInBundle不能與+startWithAppKey一起調用,+testScriptInBundle只能用于本地測試,測試完需刪除
4,發布版本
-
添加版本
- 發布補丁
5,自定義RSA密鑰和安全問題
為避免js腳本傳輸過程被中間人篡改,我們需要對js文件進行RSA簽名加密,具體流程:
服務端
計算js文件MD5值
用RSA私鑰對MD值加密,與JS文件一起下發給客戶端
客服端
拿到加密數據,用RSA公鑰解密出MD5值
本地計算返回的js文件MD5值
對比2個MD5值,相等則校驗通過,保存JS文件到本地
當保存到本地時,越獄機器會有點風險,我們可以通過對稱加密保存,然后讀取時解密。
客戶端和JSPatch后臺默認有一對RSA密鑰,默認會對這對密鑰進行加解密驗證。也可以自定義RSA密鑰。
6,自定義RSA密鑰
生成RSA密鑰。在終端輸入下列代碼后再當前目錄就有rsa_private_key.pem和rsa_public_key.pem。密鑰長度可選1024/2048/3072/4096...
openssl > genrsa -out rsa_private_key.pem 1024 pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
2,SDK設置RSA Public Key。客戶端接入SDK后調用+setupRSAPublicKey:
設置定義的RSA Public Key,必須在+sync
之前調用。Public Key以字符串方式傳入,換行處需要手動加換行符。
3,使用Private Key下發腳本。下發腳本時勾選使用自定義RSA Key 選項,選擇本地的rsa_private_key.pem與腳本一起上傳。JSPatch平臺使用上傳的Private Key對腳本MD5值進行加密,然后下發客戶端。客戶端通過第二部設置的Public Key對腳本進行驗證,通過則運行。注意:上傳的rsa_private_key.pem只是一次性使用,用戶必須保存rsa_private_key.pem文件