设备唯一标识


估计很多开发都有被要求过获取一下设备的唯一标识,获取设备的唯一标识经常使用在我们做统计或者是在保证一台设备登录亦或者是做IM的时候可能会考虑去使用它,这一次在自己的需求当中就有一个“账号绑定设备”的需求,这个需求不讨论它的实用性怎样,需求还是需要我们自己去完成。

按照自己的理解针对这个设备的唯一标识,我还是建议少拿!当然说的是针对iOS的设备。下面就来总结一下这个唯一标识的发展过程。

一: UDID


UDID是什么?

你手机连接电脑的时候会弹出iTunes,通过它你就可以直观的看到一台设备的UDID,亦或者大家应该使用过“蒲公英”这个平台,要是你传到这个平台的ipa包要能安装在一台设备上的话就需要你在你自己的开发者证书当中添加到这台设备的UDID,这个过程在你直接使用Xcode连接设备的时候,Xcode也正确添加了开发者证书的前提下也是可以直接在你的开发者当中看到设备的UDID的,这个UDID是苹果给每一台设备配发的唯一标识,要是能直接使用它的话就可以直接解决上面我们的问题,可问题的关键是:

在iOS 5 之后苹果是禁止获取该UDID了,iOS 5有点遥远了。

比如下面是通过iTunes获取到的公司的测试机的设备信息:

(有同事问我说为什么我iTunes的电话号码下面是序列号,不是UDID啊,你这是个假的iTunes吧!!哈哈....这怎么可能!你点击一下你的系列号试试!我把刀架在同事的脖子上问他是真的还是假的?)

二: IDFA


IDFA又是什么玩意?

IDFA俗称广告ID,估计在开发者里面提交用过应用的朋友都知道,在最后提交的时候苹果会问你有没有使用广告ID,不知道现在该有没有处于懵逼状态不懂苹果为什么要问这个的同行,看了我们这个就会清楚了为什么会这么问呢?这个广告ID就是IDFA。

这个IDFA既然是苹果的玩意,那是不是我们就可以安心的用了,答案肯定是不行的,苹果在用户隐私这一方面还是挺重视的,你肯定是不能用的!在手机设置中你是可以关闭这个按钮的,如下所示:

通过下面的一样代码你就能拿到这个IDFA:

    #import <AdSupport/AdSupport.h>

    NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSLog(@"拿到的广告ID:%@",idfa);

三:MAC Address 


MAC地址用来表示互联网上每一个站点的标识符,采用十六进制数表示,共六个字节(48位)。其中,前三个字节是由IEEE的注册管理机构 RA负责给不同厂家分配的代码(高位24位),也称为“编制上唯一的标识符” (Organizationally Unique Identifier),后三个字节(低位24位)由各厂家自行指派给生产的适配器接口,称为扩展标识符(唯一性)。

      MAC地址在网络上用来区分设备的唯一性,接入网络的设备都有一个MAC地址,他们肯定都是不同的,是唯一的。一部iPhone上可能有多个MAC地址,包括WIFI的、SIM的等,但是iTouch和iPad上就有一个WIFI的,因此只需获取WIFI的MAC地址就好了,也就是en0的地址。
      MAC地址就如同我们身份证上的身份证号码,具有全球唯一性。这样就可以非常好的标识设备唯一性,听着上面的解释是不是感觉很完美?
      but......
      在iOS 7.0之后你再去请求MAC地址,返回的永远都是同一个值!被禁了......

四:IDFV 也就是UUID


UUID这个你获取起来是比较容易的,但你要是想使用这个作为手机的唯一标识也是不行的,为什么?

我们用事实说明这个问题,下面的这些结论都是经过自己亲自测试的,在现有的版本中是没有问题的!!!

获取UUID,通过下面的方法:

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

下一步:你把手机的应用删除了再测试一下,我们的结论是:  要是只是单纯的这样获取UUID,删除了应用在重新安装是会发生变化的!

五:UUID + KeyChain


说了上面的这么多,这个就是这篇文章的重点内容了,你获取到UUID之后把UUID存在系统钥匙串中,你看到这个方案肯定也有下面这些疑问:

1、删除了应用这个标识会变吗?

2、升级了系统这个标识会变吗?

3、重置了系统之后呢?这个标识会变吗?

4、既然是使用到了系统钥匙串的东西,那要是我把手机越狱了,会有问题吗?

下面是我们这个方案的总的代码,先把代码给大家,完了我们再通过测试给上面的问题给出答案!给NSString添加一个UUID的类别:

//
// NSString+UUID.h
// Encapsulation
//
// Created by Zhangxu on 2018/1/26.
// 获取UUID并存储到keyChain #import <Foundation/Foundation.h> @interface NSString (UUID) + (NSString *)getUUID; @end @interface KeyChainStore : NSObject // 将UUID保存到钥匙串
+ (void)save:(NSString *)service data:(id)data;
// 读取保存到钥匙串的UUID
+ (id)load:(NSString *)service;
// 删除保存到钥匙串的UUID
+ (void)deleteKeyData:(NSString *)service; @end

上面是.h文件,下面就是 NSString+UUID.m 的文件:

//
// NSString+UUID.m
// Encapsulation
// Created by Zhangxu on 2018/1/26.
// 获取UUID并存储到keyChain #import "NSString+UUID.h" @class KeyChainStore; static NSString * KEY_USERNAME_PASSWORD = @"com.Zhushi.ShuangLongChessAndCard"; @implementation NSString (UUID) +(NSString *)getUUID
{
NSString * strUUID = (NSString *)[KeyChainStore load:KEY_USERNAME_PASSWORD];
//首次执行该方法时,uuid为空
if ([strUUID isEqualToString:@""] || !strUUID)
{
//获取UUID
strUUID = [UIDevice currentDevice].identifierForVendor.UUIDString;
//将该uuid保存到keychain
[KeyChainStore save:KEY_USERNAME_PASSWORD data:strUUID]; //iPhone 8
//11.2版本最初安装应用UUID FD6A5FE3-9EB4-422B-ADD3-17B313B9C8DE
//11.2版本删除重装应用UUID FD6A5FE3-9EB4-422B-ADD3-17B313B9C8DE
//升级系统11.2.5之后UUID FD6A5FE3-9EB4-422B-ADD3-17B313B9C8DE //iPhone 6
//10.3.3最初安装应用UUID 711CAC84-0540-4A44-80B4-26F87D2DD8B7
//10.3.3删除重装应用UUID 711CAC84-0540-4A44-80B4-26F87D2DD8B7
//升级11系统重装应用UUID 711CAC84-0540-4A44-80B4-26F87D2DD8B7
//还原系统之后的应用UUID 1236FB53-CDCE-431E-999B-5C857C679B8A }
return strUUID;
} @end #pragma mark -- KeyChainStore @implementation KeyChainStore + (NSMutableDictionary *)getKeychainQuery:(NSString *)service
{
return [NSMutableDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassGenericPassword,(id)kSecClass,
service, (id)kSecAttrService,
service, (id)kSecAttrAccount,
(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
nil];
} // 将UUID保存到钥匙串
+ (void)save:(NSString *)service data:(id)data
{
//Get search dictionary
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
//Delete old item before add new item
SecItemDelete((CFDictionaryRef)keychainQuery);
//Add new object to search dictionary(Attention:the data format)
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
//Add item to keychain with the search dictionary
SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
} // 读取保存到钥匙串的UUID
+ (id)load:(NSString *)service
{
id ret = nil;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
CFDataRef keyData = NULL;
if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr)
{
@try{
ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
} @catch (NSException *e) {
NSLog(@"Unarchive of %@ failed: %@", service, e);
} @finally {
}
}
if (keyData)
CFRelease(keyData);
return ret;
} // 删除保存到钥匙串的UUID
+ (void)deleteKeyData:(NSString *)service
{
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
SecItemDelete((CFDictionaryRef)keychainQuery);
} @end

最后的结论:

通过上面的代码你可以看到整个代码不是多么的复杂,我们关心的还是上面提出的几个疑问,我们一一测试:

1、删除了应用之后这个标识会改变吗?

结论:只要不是越狱的设备,删除应用之后是不会改变这个标识的!(越狱设备后面说!)

2、升级了系统这个标识会变吗?

下面是我把手机升级之后拿到的一组数据,测试机,就不给标识上码了...哈哈

iPhone 8

11.2版本最初安装应用UUID FD6A5FE3-9EB4-422B-ADD3-17B313B9C8DE

11.2版本删除重装应用UUID FD6A5FE3-9EB4-422B-ADD3-17B313B9C8DE

升级系统11.2.5之后UUID     FD6A5FE3-9EB4-422B-ADD3-17B313B9C8DE

iPhone 6

10.3.3最初安装应用UUID   711CAC84-0540-4A44-80B4-26F87D2DD8B7

10.3.3删除重装应用UUID   711CAC84-0540-4A44-80B4-26F87D2DD8B7

升级11系统重装应用UUID   711CAC84-0540-4A44-80B4-26F87D2DD8B7

通过上面的这组数据,我们可以得到的结论是: 在现有版本情况下,升级系统是不会改变这个标识的!

3、用于还原了设备会改变这个标识吗?我们再通过下面这组数据说明,拿我们的iPhone6当小白鼠,要是不知道怎样还原手机设备的看下面的: 设置 -> 通用 ->  还原

看我们在小白鼠上拿到的数据:

iPhone 6

10.3.3最初安装应用UUID   711CAC84-0540-4A44-80B4-26F87D2DD8B7

10.3.3删除重装应用UUID   711CAC84-0540-4A44-80B4-26F87D2DD8B7

升级11系统重装应用UUID   711CAC84-0540-4A44-80B4-26F87D2DD8B7

还原系统之后的应用UUID   1236FB53-CDCE-431E-999B-5C857C679B8A

结论: 还原系统之后我们这个标识符真的改变了!!!!

4、那要是设备越狱了呢?

结论:在越狱设备上经过测试,是偶尔可以,偶尔不行!!!没错,就是这个结论!

最后:

通过上面的对比数据分析,结果我们也给大家了,通过上面的结论,你就知道了使用 UUID + KeyChain 的利弊,在目前中你想要做唯一标识 UUID + KeyChain 暂时应该是最科学的!

iOS设备唯一标识的前世今生的更多相关文章

  1. [转]iOS设备唯一标识探讨

    转自:http://www.jianshu.com/p/b83b0240bd0e iOS设备唯一标识探讨 为了统计和检测应用的使用数据,几乎每家公司都有获取唯一标识的业务需求,在iOS5以前获取唯一标 ...

  2. 获取iOS设备唯一标识

    [获取iOS设备唯一标识] 1.已禁用-[UIDevice uniqueIdentifier] 苹果总是把用户的隐私看的很重要.-[UIDevice uniqueIdentifier]在iOS5实际在 ...

  3. ios设备唯一标识获取策略

    In iOS 7 and later, if you ask for the MAC address of an iOS device, the system returns the value 02 ...

  4. iOS设备唯一标识(可以用版)

    由于UDID和OpenUDID被禁用,系统自带的的识别唯一标识有两种 广告标示符(IDFA-identifierForIdentifier) 这是iOS 6中另外一个新的方法,advertisingI ...

  5. 获得iOS设备唯一标识

    使用-[UIDevice identifierForVendor]或是-[ASIdentifierManager advertisingIdentifier]来作为你框架和应用的唯一标示符.坦白的来说 ...

  6. iOS获取设备唯一标识的8种方法

    8种iOS获取设备唯一标识的方法,希望对大家有用. UDID UDID(Unique Device Identifier),iOS 设备的唯一识别码,是一个40位十六进制序列(越狱的设备通过某些工具可 ...

  7. ios开发——实用技术篇OC篇&获取设备唯一标识

    获取设备唯一标识 WWDC 2013已经闭幕,IOS7 Beta随即发布,界面之难看无以言表...,简直就是山寨Android. 更让IOS程序猿悲催的是,设备唯一标识的MAC Address在IOS ...

  8. iOS获取设备唯一标识的各种方法?IDFA、IDFV、UDID分别是什么含义?

    一.UDID (Unique Device Identifier) UDID的全称是Unique Device Identifier,顾名思义,它就是苹果IOS设备的唯一识别码,它由40个字符的字母和 ...

  9. 获取设备唯一标识 uuid(采用第三方库SSKeychain)

    SSKeyChain 下载链接: http://pan.baidu.com/s/1booV3VD 密码: ivdi /** *  获取设备唯一标识 uuid */ +(NSString*) uuid ...

随机推荐

  1. CodeForces801-A.Vicious Keyboard-暴力

    A. Vicious Keyboard time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  2. D. Longest Subsequence

    D. Longest Subsequence time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  3. Kafka入门介绍

    1. Kafka入门介绍 1.1 Apache Kafka是一个分布式的流平台.这到底意味着什么? 我们认为,一个流平台具有三个关键能力: ① 发布和订阅消息.在这方面,它类似一个消息队列或企业消息系 ...

  4. 使用vue-axios请求geoJson数据报错的问题

    最近的项目用到了echarts一个带有散点地图的图表,按照正常jquery写法应该使用ajax请求geojson的数据动态去切换地图,就像下面这样 $.get('Js/map/' + cityData ...

  5. vue实现侧边栏手风琴效果

    模板 代码如下 html <template> <div class="header"> <ul> <!-- 循环数据在点击调用chang ...

  6. X-Windows桌面

    提到X-Windows桌面,人们最先想到的一般都是KDE和GNOME.目前大多数的Linux发行版上的桌面环境都采用了这两个东西.确实,KDE和GNOME做得很好,界面美观.使用方便,而且现在Bug越 ...

  7. 基于TI CC2650的IPv6 over BLE(BLEach) demo

    虽然BLE 5.0协议理论上已经开始支持IPv6了,但是目前市面上还没有可用的实现IPv6通信的BLE产品. 最近在网上看到一个开源的基于contiki系统,在CC2650上实现的IPv6 over ...

  8. 通过自定义的URL Scheme启动你的App

    iPhone SDK可以把你的App和一个自定义的URL Scheme绑定.该URL Scheme可用来从浏览器或别的App启动你的App. 如何响应从别的App里发给你的URL Scheme申请,由 ...

  9. 【编程技巧】EXTJS中Ext.grid.GridPanel配置项autoExpandColumn的使用方法

    autoExpandColumn的作用是自动伸展,占满剩余区域.一般使用在列比较少,并且大多数列都比较窄,有一列比较宽的情况下,当然什么时候使用,还是得按照实际情况确定. 使用的时候主要有三点要注意的 ...

  10. jQuery.fn的作用是什么

    jQuery.fn的作用是什么:在自定义jQuery插件中,会经常见到jQuery.fn的身影,下面就简单介绍一下它的作用到底是什么.想要认识它的本质,最好的办法直接看jQuery的源码,否则一切都是 ...