iOS设备唯一标识的前世今生
设备唯一标识
估计很多开发都有被要求过获取一下设备的唯一标识,获取设备的唯一标识经常使用在我们做统计或者是在保证一台设备登录亦或者是做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位)由各厂家自行指派给生产的适配器接口,称为扩展标识符(唯一性)。
四: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设备唯一标识的前世今生的更多相关文章
- [转]iOS设备唯一标识探讨
转自:http://www.jianshu.com/p/b83b0240bd0e iOS设备唯一标识探讨 为了统计和检测应用的使用数据,几乎每家公司都有获取唯一标识的业务需求,在iOS5以前获取唯一标 ...
- 获取iOS设备唯一标识
[获取iOS设备唯一标识] 1.已禁用-[UIDevice uniqueIdentifier] 苹果总是把用户的隐私看的很重要.-[UIDevice uniqueIdentifier]在iOS5实际在 ...
- ios设备唯一标识获取策略
In iOS 7 and later, if you ask for the MAC address of an iOS device, the system returns the value 02 ...
- iOS设备唯一标识(可以用版)
由于UDID和OpenUDID被禁用,系统自带的的识别唯一标识有两种 广告标示符(IDFA-identifierForIdentifier) 这是iOS 6中另外一个新的方法,advertisingI ...
- 获得iOS设备唯一标识
使用-[UIDevice identifierForVendor]或是-[ASIdentifierManager advertisingIdentifier]来作为你框架和应用的唯一标示符.坦白的来说 ...
- iOS获取设备唯一标识的8种方法
8种iOS获取设备唯一标识的方法,希望对大家有用. UDID UDID(Unique Device Identifier),iOS 设备的唯一识别码,是一个40位十六进制序列(越狱的设备通过某些工具可 ...
- ios开发——实用技术篇OC篇&获取设备唯一标识
获取设备唯一标识 WWDC 2013已经闭幕,IOS7 Beta随即发布,界面之难看无以言表...,简直就是山寨Android. 更让IOS程序猿悲催的是,设备唯一标识的MAC Address在IOS ...
- iOS获取设备唯一标识的各种方法?IDFA、IDFV、UDID分别是什么含义?
一.UDID (Unique Device Identifier) UDID的全称是Unique Device Identifier,顾名思义,它就是苹果IOS设备的唯一识别码,它由40个字符的字母和 ...
- 获取设备唯一标识 uuid(采用第三方库SSKeychain)
SSKeyChain 下载链接: http://pan.baidu.com/s/1booV3VD 密码: ivdi /** * 获取设备唯一标识 uuid */ +(NSString*) uuid ...
随机推荐
- BZOJ 2219: 数论之神
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2219 N次剩余+CRT... 就是各种奇怪的分类讨论.. #include<cstrin ...
- poj_2503(map映射)
题目链接poj2503 Babelfish Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 38820 Accepted: ...
- c++只能编译无法运行或许缺少命令
-mwindows -lcomctl32 -lwinmm -lws2_32 -lodbc32 -lmysql -lwinspool1.工具-编译选项-编译器-在连接器命令行加入以下命令:-mwin ...
- Win10下安装RabbitMQ以及基本知识学习
一.为什么选择RabbitMQ? 先说一下场景,这是我们公司遇到,当然我这里不做业务评价哈?虽然我知道他很不合理,但是我是无能为力的.APP端部分注册是Java开发的系统,然后业务端是C#开 ...
- Java数据结构和算法(十二)——2-3-4树
通过前面的介绍,我们知道在二叉树中,每个节点只有一个数据项,最多有两个子节点.如果允许每个节点可以有更多的数据项和更多的子节点,就是多叉树.本篇博客我们将介绍的——2-3-4树,它是一种多叉树,它的每 ...
- Debug模式下程序卡
Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用. D ...
- 算法-java代码实现堆排序
堆排序 第7节 堆排序练习题 对于一个int数组,请编写一个堆排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3],6 [1,2 ...
- java 静态导入 小结
之前看过静态导入这一块,在编程思想里,但是记不清了,今天搜了下,看到有一个博文写的不错,所以留做备注吧 总结: import static xxx.xxx 和普通导入的区别在于,普通导入是需要通过& ...
- 微软Azure AspNetCore微服务实战第2期
2018年1月28日,虽然上海的大雪在城区已经见不到踪影,但还是很冷.不过天气再冷,也阻止不了小伙伴参加活动的热情. 感谢王振,苏老师以及微软Azure API Management的产品经理Alvi ...
- HEXO+Github,搭建属于自己的博客
摘录自:http://www.jianshu.com/p/465830080ea9 1. github的准备 账号 密码 建立Repository建立与你用户名对应的仓库,仓库名必须为[your_us ...