关于设备唯一标识

原文连接

什么是设备唯一标识?

设备的唯一标识,当前设备的生成字符串,保证与其他设备相比唯一且不变,一版利用于产品的统计的访问次数或用户操作的统计.

设备唯一标识的获取:

在IOS5.0之前:使用UDID(Unique Device Identifier),是苹果IOS设备的唯一识别码,它由40个字符的字母和数字组成,生成方法:

1NSString *uuid = [[UIDevice currentDevice] uniqueIdentifier]

IOS5.0之后,苹果不建议开发者使用UDID,并且获取设备UDID的方法已经被苹果的SDK中标识为弃用,又有人爆出苹果App Store禁止访问UDID的应用上架,许多开发者都弃用UDID,去寻找另外的替代方案. 分别有以下几种:

1. 苹果公司建议的UUID替代方案.

-(NSString*) uuid {   

    CFUUIDRef puuid = CFUUIDCreate( nil );   

    CFStringRef uuidString = CFUUIDCreateString( nil, puuid );   

    NSString * result = (NSString *)CFStringCreateCopy( NULL, uuidString);   

    CFRelease(puuid);   

    CFRelease(uuidString);   

    return [result autorelease];   

}

苹果公司建议采用上述代码为应用生成唯一标识字符串。开发者可以在应用第一次启动时调用一次,然后将该串存储起来,以便以后替代UDID来使用。显而易见,这种方法问题很多。如果用户删除该应用再次安装时,又会生成新的字符串,所以不能保证唯一识别该设备;如果你从一台旧设备中备份文件到新设备中,两台设备就拥有相同的CFUUID;如果你从临时文件中备份操作系统,就会出现一个设备里存在不同CFUUID的情况.

2. 开源方案OpenUDID.

其生成标识的代码为:

unsigned char result[16]; 

const char *cStr = [[[NSProcessInfo processInfo] globallyUniqueString] UTF8String]; 

CC_MD5( cStr, strlen(cStr), result ); 

_openUDID = [NSStringstringWithFormat: 

            @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%08x", 

            result[0], result[1], result[2], result[3],  

            result[4], result[5], result[6], result[7], 

            result[8], result[9], result[10], result[11], 

            result[12], result[13], result[14], result[15], 

            arc4random() % 4294967295];

其中用到了NSProcessInfo类,为了于UDID40位长度相同,后面还添加了8为的随机数,主要就是把当前生成的字符串存在NSUserDefults里面,以供程序使用,还把当前生成的字符串存进UIPasteboard类(设备剪切板)代码如下:

UIPasteboard* slotPB = [UIPasteboardpasteboardWithName:availableSlotPBid create:YES];     

[slotPB setData:[NSKeyedArchiver archivedDataWithRootObject:dict] forPasteboardType:kOpenUDIDDomain];

如果设备上安装了第二个使用OpenUDID解决方案的应用,当应用调用生成OpenUDID的方法时,将会从UIPasteboard中获取唯一识别码,这里取到的就是之前第一个应用保存到UIPasteboard中的。也就是说,只要用户设备上有一个使用了OpenUDID的应用存在时,其他后续安装的应用如果获取OpenUDID,都将会获得第一个应用生成的那个。

看起来似乎很好,很复杂。但是仔细想想,还是有问题,如果把使用了OpenUDID方案的应用全部都删除,再重新获取OpenUDID,此时的OpenUDID就跟以前的不一样了(本人测了一下,确实如此)。可见,这种方法还是不保险。

3. 开源方案SecureUDID:

稍微看了下SecureUDID源码,发现其与OpenUDID其实差不多,只是初始获取的唯一识别码稍有不同。同时,从作者的Readme文档中可见,这个方案同样存在很多问题。如原文:

Is this a true UDID replacement?

SecureUDID has two properties that you should know about before you use it. First, as indicated above, the identifier is not derived from hardware attributes. Second, the persistence of an identifier cannot be guaranteed in all situations. This means that, while unlikely, it is technically possible for two distinct devices to report the same identifier, and for the same device to report different identifiers. Consider this carefully in your application. Here is a list of situations where this identifier will not exhibit the uniqueness/persistence of a traditional UDID.

* The user has opted-out of the SecureUDID system, in which case you will receive a well-formed string of zeroes.

* Device A is backed up and then restored to Device B, which is an identical model. This is common when someone breaks their phone, for example, and is likely desirable: you will receive Device A's SecureUDID.

* The SecureUDID data is removed, via user intervention, UIPasteboard data purge, or by a malicious application.

* The SecureUDID backing store becomes corrupt.

* All SecureUDID applications are uninstalled from a device, followed by a UIPasteboard data purge.

我发现,其实前面的OpenUDID也基本存在以上问题,只是作者没写出来。看来还是SecureUDID的贡献者比较厚道。

4. 与WIFI MAC地址相关

网上同样有一些与WIFI MAC地址相关的替代方案,主要分三种:第一种直接使用“MAC Address”;第二种,使用“MD5(MAC Address)”;第三种,“MD5(MAC Address+CFBundleIdentifier)”。github上有个开源项目(UIDevice-with-UniqueIdentifier-for-iOS-5)实现了这几种方法。

使用这种方法也存在问题:1、市面上有部分机器(虽然数量极少,但是本人在使用过程中确实发现过这种情况)无法获得MAC地址,有人说这部分机器是联通阉割无WIFI版的,具体不得而知了。2、MAC地址跟UDID一样,存在隐私问题。

在IOS7.0之后有一些变动 : 

1. 苹果在新的SDK中把获取UDID的API删除,iOS7之前的使用了-[UIDevice uniqueIdentifier] 的app如果在iOS7上运行,它不会返回设备的UUID,而是会返回一串字符串,以FFFFFFFF开头,跟着-[UIDevice identifierForVendor]的十六进制值 ; 

2. UIPasteboard由共享变为沙盒化了,这样一来以上使用的UUID可能不像以前那么强大了 ; 

3. MAC地址不能再用来设别设备,苹果并不希望有人通过MAC地址来分辨用户,所以如果你在iOS7系统上查询MAC地址,它现在只会返回02:00:00:00:00:00

现在苹果明确的表明你应该使用-[UIDevice identifierForVendor]或是-[ASIdentifierManager advertisingIdentifier]来作为你框架和应用的唯一标示符。坦白的来说,应对这些变化也不是那么的难,见以下代码片段:

NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];

NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];

每种方法都适配一种特别的用法:

identifierForVendor对供应商来说是唯一的一个值,也就是说,由同一个公司发行的的app在相同的设备上运行的时候都会有这个相同的标识符。然而,如果用户删除了这个供应商的app然后再重新安装的话,这个标识符就会不一致。

advertisingIdentifier会返回给在这个设备上所有软件供应商相同的 一个值,所以只能在广告的时候使用。这个值会因为很多情况而有所变化,比如说用户初始化设备的时候便会改变。

你可能感兴趣的:(关于设备唯一标识)