iOS之热更新/热修复JSPatch 补丁更新管理

74 篇文章 7 订阅
33 篇文章 0 订阅

总结:

1、在传输过程中对JS文件进行了RSA签名加密;

2、下载完脚本保存到本地时,应进行简单的对称加密,每次读取时解密;

3、建议js脚本的增、删、改、查的内容在同一个js文件处理,只下载一个文件就OK。

 

 

 

 

 

上一篇了解工作原理后,这篇谈谈一下自行搭建管理后台实现补丁更新的基本思路。

先假设遇到以下问题:App发行了两个版本,V1.0和V2.0,上线投产后发现V1.0存在bug1,V2.0存在bug2;

 

前提准备:

a、本地生成RSA密钥对,公钥可以公开,打包作为配置常量放进ipa文件,私钥自己保管好,存放在如PSAM卡、带加密功能的磁盘载体等。

b、制作好的脚本文件(即补丁)。

 

基本原理:安装本地所有补丁 –> 联网更新补丁信息,并安装有更新或新增加的补丁。

具体流程:

1、在管理后台新建需要更新补丁的版本号,然后上传bug文件(*.js)。上传脚本时,选择本地的 rsa_private_key.pem (RSA私钥)文件,与脚本一同上传,管理平台会使用这个上传的 Private Key 对脚本 MD5 值进行加密,得到加密结果并与该脚本文件一一对应保存起来。

2、客户端判断本地是否有脚本,有则在程序开始的时候加载执行(若文件对称加密了需先解密),无则跳过;

3、客户端联网请求补丁更新,上传时参数带版本信息(如版本号),查询当前版本是否有bug。

4、管理平台会只针对这个版本号下发对应的 JS 脚本(实现对V1.0和V2.0分别处理),若版本号对应不上或无bug,客户端也就请求不到相应的 JS 脚本;若有bug,由服务器返回step1的脚本和加密MD5值。

5、客户端计算脚本的MD5值(MD5_1),通过内置的RSA公钥解密 step4 的MD5得到值MD5_2,比较MD5_1和MD5_2是否相同,能够解密得出来并结果相同,说明加密者一定是使用了step1中RSA私钥,服务器返回数据可信,先保存到App本地缓存(保存到本地时可进行简单的对称加密,每次读取时解密)。

6、以后App每次启动,都需要加载并执行本地已保存好的这个脚本(即上面的step2),这样就可以实现补丁更新了。

 

注意:这里上传的 rsa_private_key.pem 只是一次性使用,不会保存在服务端,所以只有通过用户自己保存的 rsa_private_key.pem 文件才可以针对 APP 下发脚本,即使管理平台被黑,黑客也无法对你的 APP 下发恶意脚本(可以下发,但验证不过,不会执行),保证安全性。rsa_private_key.pem 请妥善保管,避免泄露。

 

 

 

待讨论:上面步骤中,补丁文件没有强制更新,它只会加载上一次已下载好的脚本。假设在AppDelegate中加载脚步,且客户端一直休眠在系统后台没有重启,那么这种方案无法对每一个用户实现即时修复。有人说,那好办,我在程序入口处设置必须拉取服务器脚本成功后才能进入程序界面,这样可以强制用户实现即时修复,我觉得也是有问题的:如果网络不稳定,拉取请求失败,客户端应该如何呈现?是退出(用户体验不好)还是跳转到程序界面(这样就无法在本地执行脚本)呢?

 

App需要具备 “增、删、改、查” 功能

其他问题:如果V1.0新发现了bug3;或者发现上一次脚步内容有纰漏需要修改;或者取消这个版本的补丁,客户端和服务器应该如何应对?这就要求app需要具备 “增、删、改、查” 功能。

 

增:服务器返回的补丁,本地不存在时,会默认下载存储,并执行.
删: 服务器返回的补丁集中,不包含本地的某个补丁,则此补丁下次不会再被执行.
改: 服务器返回的补丁,本地包含,但md5值变化,此时会重新下载此补丁.
查: 会默认在应用启动时,执行所有存在,且md5值匹配的补丁.补丁集的信息,会在每次联网更新时更新.此处使用的是一个缓存库

 

补丁状态的管理详见点击打开链接
 

优化:鉴于上述步骤可能会存在操作复杂性,采用一次性下载所有可能会更好:把增、删、改、查的内容全部写到一个js文件,

1、客户端每次请求时先搜索本地是否有js文件并计算MD5值,若无值则不传,若有则新增传MD5值;

2、服务器判断MD5 不为空,进行两个MD5值比对,不一致下发脚本;

3、客户端缓存脚本(首次下载)或替换脚本(本地已缓存)

这里要注意删除脚本问题,如果后台把所有脚本删除了,那么客户端也要根据返回的空白内容删除本地缓存。

 


Mac电脑获取某个文件的md5值直接在终端输入命令:

md5 文件完整路径


Objective-C获取某个文件的md5值

 

 

#include <CommonCrypto/CommonDigest.h>:

/**
 *  获取文件的md5值.
 *  @param path 文件路径.
 *  @return 文件的md5值.
 */
-(NSString *)mcMd5HashOfPath:(NSString *)path
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    // 确保文件存在.
    if( [fileManager fileExistsAtPath:path isDirectory:nil] )
    {
        NSData *data = [NSData dataWithContentsOfFile:path];
        unsigned char digest[CC_MD5_DIGEST_LENGTH];
        CC_MD5( data.bytes, (CC_LONG)data.length, digest );

        NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
        for( int i = 0; i < CC_MD5_DIGEST_LENGTH; i++ ) {
            [output appendFormat:@"%02x", digest[i]];
        }

        return output;
    }
    else
    {
        return @"";
    }
}

 

 

 

在工程中放一个demo.js供Debug模式下调试

/**
 *  测试模式下,会执行此方法,以验证某个JS文件的作用.默认使用本地demo.js.
 */
- (void)mcDebug
{
#ifdef DEBUG
    NSString * path = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
    [self mcEvaluateScriptFile: path];
#endif
}

 

 

 

jspatch解决AppStore审查机制解决方案是:点击打开链接

参考:点击打开链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值