iOS渠道分包2种模式之包内注入文件分包(iOS13验证签名问题)

时间:2024-01-25 15:15:25

解决问题:商业模式中会存在这样的形式1款app需要不同的运用团队(工会)去分包推广,谁推广的包下载的人数都会在服务器记录,不同渠道的标示唯一来区分。

 

iOS渠道分包模式有两种着重讲第二种

一、IDFA模式

IDFA全称应该是Identifier For Advertising, 一个跟device相关的唯一标识符,可以理解为广告id,apple公司提供的用于追踪用户的广告标识符,可以用来打通不同app之间的广告。适用于对外:例如广告推广,换量等跨应用的用户追踪等。比如你在淘宝里搜索了某个商品之后,你在用浏览器去浏览网页的时候,那个网页的广告就会给你展示相应的那个商品的广告。当然你可以重置你的IDFA,使别人不能再track到你的行为。

缺点:如果用户完全重置系统((设置程序 -> 通用 -> 还原 -> 还原位置与隐私) ,这个广告标示符会重新生成。 另外如果用户明确的还原广告(设置程序-> 通用 -> 关于本机 -> 广告 -> 还原广告标示符) ,那么广告标示符也会重新生成

因为IDFA是可以改变的,所以之前很多人都想拿到一个唯一不变的值比如说UDID(Unique Device Identifier, 这个是跟手机绑定的,用户不能更改),但是Apple后来禁止苹果应用获取UDID。所以现在IDFA成为了iphone用户的标识符的标准。

IDFA是一串16进制的32位串。有了IDFA之后,相当于广告追踪,你所有的浏览历史都会被别的商家利用,给你推相同或相似的广告。

另外一个apple上可以用到的标识符是UUID,Universally Unique IDentifier,在应用程序使用生命期间,这个 UUID保持不变。但如果用户重新安装,那么这个 UUID 就会发生变化。

还有一个类似的标识符叫做IDFV,Identifier for Vendor, 来自同一个开发商比如亚马逊下边的购物app和kindle app,此值是相同的。这样可以做到同一开发商下的不同app做到信息共享。

关于广告标示符的还原,有一点需要注意:如果程序在后台运行,此时用户“还原广告标示符”,然后再回到程序中,此时获取广 告标示符并不会立即获得还原后的标示符。必须要终止程序,然后再重新启动程序,才能获得还原后的广告标示符。

在同一个设备上的所有App都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设的,用户可以在 设置|隐私|广告追踪 里重置此id的值,或限制此id的使用,故此id有可能会取不到值,但好在Apple默认是允许追踪的,而且一般用户都不知道有这么个设置,所以基本上用来监测推广效果,是戳戳有余了。

注意:由于idfa会出现取不到的情况,故绝不可以作为业务分析的主id,来识别用户。 

因此,IDFA就是用来跟踪广告推广的,而UUID虽然每次不同,但是可以自己手动存入Keychain来进行唯一性的确保,这么说来IDFA就是广告商投放的时候使用,而UUID就是自己后台来判断用户是否换了设备,或者信息不一致需要重新登录的业务。

好了, 总结一下这三个标识符:

UUID, app之内信息共享。

IDFV, 同一开发商下的不同app信息共享。

IDFA,同一设备下的不同app信息共享。

二、母包(没有种植文件的叫母包,种植完文件的叫子包,母包只有一个用来种植,子包可以多个)种植文件的形式

1、我们随便打一个ipa包;

2、然后通过后台或者window电脑注入一个文件-我们定义文件名为channel_xxxx(xxxx为渠道id);

key:关键来了我们怎么注入一个文件才能在用户打开app的时候取到这个文件名?

 

 

3、然后会有一个文件路径12345->Payload->bixinlive,然后bixinlive显示包内容:里边有一个_CodeSignature文件(这个文件是验证签名的文件),在他的路径下注入一个名字问channel_EFS89V的文件;

 

4、代码取到这个文件的文件名; 

 NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
          NSString *path = [NSString stringWithFormat:@"%@/%@", bundlePath, @"_CodeSignature"];
    NSFileManager *manager = [NSFileManager defaultManager];
    NSString *channel = @"";
    if ([manager fileExistsAtPath:path]) {
       NSArray *allPath =[manager subpathsAtPath:path];
          //4.遍历所有的子路径
          for (NSString *subPath in allPath) {
              if ([subPath containsString:@"channel_"]) {
                  channel = [subPath substringFromIndex:@"channel_".length];
              }
          }
    }
//然后请求接口把渠道id传给后台。

iOS13签名验证这种方式会验证签名不通过;

三、解决iOS13的问题

iOS13会验签_CodeSignature的文件的所有内容文件;

所以我们要换一种方案;

偶然发现苹果在验证签名的时候不会验签文件夹。所以我们只需要在_CodeSignature同一级别文件夹(非子文件夹)种植一个文件夹channel,文件夹内同样的有一个文件夹(记住都要是文件夹)名字为channel_EFS89V通过二的方式去文件夹的名字。

然后取文件夹的名字作为渠道id

 AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
    NSString *path2 = [NSString stringWithFormat:@"%@/%@", bundlePath, @"channel"];

   NSFileManager *manager = [NSFileManager defaultManager];
   NSString *channel = @"";
    if ([NSString isEmpty:channel]) {
        if ([manager fileExistsAtPath:path2]) {
            NSArray *allPath =[manager subpathsAtPath:path2];
            //4.遍历所有的子路径
            for (NSString *subPath in allPath) {
                if ([subPath containsString:@"channel_"]) {
                    channel = [subPath substringFromIndex:@"channel_".length];
                }
            }
        }
    }
//取到的channel问渠道id,然后吧channel作为渠道id传给后台接口内