【转】iOS设备的UDID是什么?苹果为何拒绝获取iOS设备UDID的应用?如何替代UDID?


本文讲诉的主要是为何苹果2011年8月发布iOS 5后就开始拒绝App获取设备的UDID以及UDID替补方案,特别提醒开发者苹果App Store禁止访问UDID的应用上架(相关推荐:APP被苹果App Store拒绝的N个缘由),下面先来了解下UDID。html

1、UDID是什么?

UDID的全称是Unique Device Identifier,顾名思义,它就是苹果IOS设备的惟一识别码,它由40个字符的字母和数字组成。git

2、UDID有什么用?

移动网络可利用UDID来识别移动设备,如iPhone和iPad。UDID对每台设备而言都是惟一的,从而成为了广告公司、市场分析机构和APP测试系统跟踪用户行为的实用工具。github

目前使用UDID主要缘由分为:web

 

  • 1)用于统计与分析,例如第三方统计工具Flurry、友盟等,广告商ADMOB等;
  • 2)将UDID做为用户ID来惟一识别用户,省去用户名,密码等注册过程。

 


因而可知UDID对于IOS应用开发者说,是个很重要的信息(虽然越狱的设备经过某些工具能够改变设备的UDID)。可是,从IOS5.0(2011年8月份)开始,苹果宣布将再也不支持用如下方法获取设备的UDID。网络

 

1
[UIDevice currentDevice ]  uniqueIdentifier ];

3、拒绝 iOS 应用获取设备的 UDID的缘由

UDID原本是为了方便一个应用来统计用户行为的,可是由于是一个惟一ID,并且直接看不到跟用户隐私的关系,因此是开放出来的。可是,当有大量的App在市场中,而UDID对于每一个App都是同样的时候,用户的隐私其实受到了必定程度的侵犯。假设有不少App联合在一块儿,由于UDID是统一的,那么他们就能够拼凑出用户的隐私出来。因此从这个角度苹果去掉了UDID的支持,而每一个应用能够自行生成本身的UUID,因此,单一app的统计仍旧不会发生问题。因此主要的缘由是隐私问题。app

4、必须使用UDID时建议的UUID替代方案

一、苹果公司建议的UUID替代方案dom

1
2
3
4
5
6
7
8
- ( 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的状况。iphone

二、使用开源方案OpenUDID
贡献者在readme文档中说:ide

 

OpenUDID is a drop-in replacement for the deprecated [UIDevice uniqueIdentifier] a.k.a. UDID on iOS, and otherwise is an industry-friendly equivalent for iOS and Android.
The agenda for this community driven project is to: – Provide a reliable proxy and replacement for a universal unique device identifier. That is, persistent and sufficiently unique, on a per device basis. – NOT use an obvious other sensitive unique identifier (like the MAC address) to avoid further deprecation and to protect device-level privacy concerns – Enable the same OpenUDID to be accessed by any app on the same device – Supply open-source code to generate and access the OpenUDID, for iOS and Android – Incorporate, from the beginning, a system that will enable user opt-out to match Apple’s initial intent.工具

愿景很好,也确实没有用到MAC地址,同时能保证同一台设备上的不一样应用使用同一个OpenUDID。可是仔细分析,仍是能发现问题。
OpenUDID生成惟一识别码的代码是:

1
2
3
4
5
6
7
8
9
10
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类。
当设备上第一个使用OpenUDID解决方案的应用第一次调用时,确实会生成一个惟一的识别码。同时,为了与官方的UDID位数相同,还在MD5值后面追加了8位随机码。而后,该方案使用到了NSUserDefaults类(应用设置)。应用将获取到的惟一识别码保存到应用的UserDefaults中,若是程序之后须要使用惟一识别码,就从UserDefaults中获取,这样就保证能够拿到同一个识别码。可是,若是用户删除了应用,UserDefaults一样会被清空,为了不从新生成惟一识别码,该方案还使用到了UIPasteboard类(设备剪切板)。应用在将惟一识别码保存到UserDefaults的同时,也会将其保存到以特殊的key标识的UIPasteboard中。代码如:

1
2
UIPasteboard *  slotPB   =   [UIPasteboardpasteboardWithName :availableSlotPBid create : YES ];    
[slotPB setData : [ NSKeyedArchiver  archivedDataWithRootObject :dict ]  forPasteboardType :kOpenUDIDDomain ];

其中availableSlotPBid是一个字符串key,前缀是“org.OpenUDID.slot.”,点后面加上数字。这个数字默认是从0到99(固然你能够修改源代码使它更大或者更小)。
若是设备上安装了第二个使用OpenUDID解决方案的应用,当应用调用生成OpenUDID的方法时,将会从UIPasteboard中获取惟一识别码(遍历key从0到99的UIPasteboard),这里取到的就是以前第一个应用保存到UIPasteboard中的。也就是说,只要用户设备上有一个使用了OpenUDID的应用存在时,其余后续安装的应用若是获取OpenUDID,都将会得到第一个应用生成的那个。
看起来彷佛很好,很复杂。可是仔细想一想,仍是有问题,若是把使用了OpenUDID方案的应用所有都删除,再从新获取OpenUDID,此时的OpenUDID就跟之前的不同了(本人测了一下,确实如此)。可见,这种方法仍是不保险。

三、开源方案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的贡献者比较厚道。
四、与WIFI MAC地址相关
网上一样有一些与WIFI MAC地址相关的替代方案,主要分三种:第一种直接使用“MAC Address”;第二种,使用“MD5(MAC Address)”;第三种,“MD5(MAC Address+CFBundleIdentifier)”。github上有个开源项目(UIDevice-with-UniqueIdentifier-for-iOS-5)实现了这几种方法。
使用这种方法也存在问题:一、市面上有部分机器(虽然数量极少,可是本人在使用过程当中确实发现过这种状况)没法得到MAC地址,有人说这部分机器是联通阉割无WIFI版的,具体不得而知了。二、MAC地址跟UDID同样,存在隐私问题。苹果如今禁用UDID,不能保证之后不会禁用MAC地址。

五、部分大公司私有的解决方案,可是他们怎么会告诉你呢?

因此,若是你想以一种万无一失的方法追踪某台设备,如今尚未比UDID更合适的选择。可是,苹果如今不让用了,苦逼的开发者们,该怎么办呢?

 

转自:http://www.dapps.net/dev/iphone/whats-udid-and-how-to-replace-udid.html

by sschu

相关文章
相关标签/搜索