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

8种iOS获取设备唯一标识的方法,希望对大家有用。

UDID

UDID(Unique Device Identifier),iOS 设备的唯一识别码,是一个40位十六进制序列(越狱的设备通过某些工具可以改变设备的 UDID),移动网络可以利用 UDID 来识别移动设备。

许多开发者把 UDID 跟用户的真实姓名、密码、住址、其它数据关联起来,网络窥探者会从多个应用收集这些数据,然后顺藤摸瓜得到这个人的许多隐私数据,同时大部分应用确实在频繁传输 UDID 和私人信息。 为了避免集体诉讼,苹果最终决定在 iOS 5 的时候,将这一惯例废除。

现在应用试图获取 UDID 已被禁止且不允许上架。

MAC 地址

MAC(Medium / Media Access Control)地址,用来表示互联网上每一个站点的标示符,是一个六个字节(48位)的十六进制序列。前三个字节是由 IEEE 的注册管理机构 RA 负责给不同厂家分配的”编制上唯一的标示符(Organizationally Unique Identifier)”,后三个字节由各厂家自行指派给生产的适配器接口,称为扩展标示符。

MAC 地址在网络上用来区分设备的唯一性,接入网络的设备都有一个MAC地址,他们肯定都是唯一的。一部 iPhone 上可能有多个 MAC 地址,包括 WIFI 的、SIM 的等,但是 iTouch 和 iPad 上就有一个 WIFI 的,因此只需获取 WIFI 的 MAC 地址就好了。一般会采取 MD5(MAC 地址 + bundleID)获取唯一标识。

但是 MAC 地址和 UDID 一样,存在隐私问题, iOS 7 之后,所有设备请求 MAC 地址会返回一个固定值,这个方法也不攻自破了。

OpenUDID

UDID 被弃用后,广大开发者需要寻找一个可以替代的 UDID,并且不受苹果控制的方案,由此,OpenUDID 成为了当时使用最广泛的开源 UDID 代替方案。OpenUDID 利用一个非常巧妙的方法在不同程序间存储标示符:在粘贴板中用了一个特殊的名称来存储标示符,通过这种方法,其他应用程序也可以获取。

苹果在 iOS 7 之后对粘贴板做了限制,导致同一个设备上的应用间,无法再共享一个 OpenUDID。

UUID + 自己存储

UUID(Universally Unique IDentifier),通用唯一标示符,是一个32位的十六进制序列,使用小横线来连接:8-4-4-4-12,通过 NSUUID(iOS 6 之后)[NSUUID UUID].UUIDString 或者 CFUUID(iOS 2 之后) CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, CFUUIDCreate(kCFAllocatorDefault))) 来获取,但是每次获取的值都不一样,需要自己存储。

推送 token + bundleID

推送 token 保证设备唯一,但是必须有网络情况下才能工作,该方法不依赖于设备本身,但依赖于 apple push,而 apple push 有时候会抽风的。

IDFA

IDFA-identifierForIdentifier(广告标示符),在同一个设备上的所有 APP 都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设定的。虽然 iPhone 默认是允许追踪的,而且一般用户都不知道有这么个设置,但是用户可以在 设置 - 隐私 - 广告追踪 里重置此 ID 的值,或者限制此 ID 的使用,所以有可能会取不到值。

IDFV

IDFV-identifierForVendor(Vendor 标示符),通过 [UIDevice currentDevice].identifierForVendor.UUIDString 来获取。是通过 bundleID 的反转的前两部分进行匹配,如果相同是同一个 Vendor ,例如对于 com.mayan.app_1 和 com.mayan.app_2 这两个 bundleID 来说,就属于同一个 Vendor ,共享同一个 IDFV,和 IDFA 不同的是,IDFV 的值一定能取到的,所以非常适合于作为内部用户行为分析的主 ID 来识别用户。但是用户删除了该 APP ,则 IDFV 值会被重置,再次安装此 APP ,IDFV 的值和之前的不同。

IDFV + keychain

通过以上几种储存唯一标识的方法的分析,总结一下各有优劣。很多方法被苹果禁止或者漏洞太多,越来越不被开发者使用,现在苹果主推 IDFA 和 IDFV 这两种方法,分别对外和对内,但是 IDFV 在 APP 重新安装时会更改,所以我的方法是通过第一次生成的 IDFV 存储到 keychain 中,以后每次获取标识符都从 keychain 中获取。

#import <UIKit/UIKit.h>
@interface MYVendorToll : NSObject
+ (NSString *)getIDFV;
@end
#import "MYVendorToll.h"
#import "MYKeyChainTool.h"

@implementation MYVendorToll

+ (NSString *)getIDFV
{
 NSString *IDFV = (NSString *)[MYKeyChainTool load:@"IDFV"];

 if ([IDFV isEqualToString:@""] || !IDFV) {

  IDFV = [UIDevice currentDevice].identifierForVendor.UUIDString;
  [MYKeyChainTool save:@"IDFV" data:IDFV];
 }

 return IDFV;
}

@end
#import <Foundation/Foundation.h>

@interface MYKeyChainTool : NSObject

+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)deleteKeyData:(NSString *)service;

@end
#import "MYKeyChainTool.h"

@implementation MYKeyChainTool

+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
 return [NSMutableDictionary dictionaryWithObjectsAndKeys:
   (id)kSecClassGenericPassword,(id)kSecClass,
   service, (id)kSecAttrService,
   service, (id)kSecAttrAccount,
   (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
   nil];
}

+ (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);
}

+ (id)load:(NSString *)service {
 id ret = nil;
 NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
 //Configure the search setting
 //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
 [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;
}

+ (void)deleteKeyData:(NSString *)service {
 NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
 SecItemDelete((CFDictionaryRef)keychainQuery);
}

@end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • iOS 获取设备唯一标示符的方法详解

    在开发中会遇到应用需要记录设备标示,即使应用卸载后再安装也可重新识别的情况,在这写一种实现方式--读取设备的UUID(Universally Unique Identifier)并通过KeyChain记录. 首先iOS中获取设备唯一标示符的方法一直随版本的更新而变化.iOS 2.0版本以后UIDevice提供一个获取设备唯一标识符的方法uniqueIdentifier,通过该方法我们可以获取设备的序列号,这个也是目前为止唯一可以确认唯一的标示符.好景不长,因为该唯一标识符与手机一一对应,苹果觉得

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

    8种iOS获取设备唯一标识的方法,希望对大家有用. UDID UDID(Unique Device Identifier),iOS 设备的唯一识别码,是一个40位十六进制序列(越狱的设备通过某些工具可以改变设备的 UDID),移动网络可以利用 UDID 来识别移动设备. 许多开发者把 UDID 跟用户的真实姓名.密码.住址.其它数据关联起来,网络窥探者会从多个应用收集这些数据,然后顺藤摸瓜得到这个人的许多隐私数据,同时大部分应用确实在频繁传输 UDID 和私人信息. 为了避免集体诉讼,苹果最终决

  • iOS获取设备唯一标识的实现步骤

    目录 1. 常用的UUID 2. MAC 地址 2.1 首先导入下面几个库: 2.2 新建一个文件,继承NSObject,在.m文件导入头文件,以及定义一些宏 3.UUID+自己存储 3.1 获取UUID的两个方法 3.2 首先在项目中添加 KeyChain Sharing 3.3 导入第三方库 Security.framework 3.4 核心代码(代码有点多) 3.4 创建新类,引用 SSKeychain 封装 1. 常用的UUID UDID是一个40位十六进制序列(越狱的设备通过某些工具可

  • 浅谈android获取设备唯一标识完美解决方案

    本文介绍了浅谈android获取设备唯一标识完美解决方案,分享给大家,具体如下: /** * deviceID的组成为:渠道标志+识别符来源标志+hash后的终端识别符 * * 渠道标志为: * 1,andriod(a) * * 识别符来源标志: * 1, wifi mac地址(wifi): * 2, IMEI(imei): * 3, 序列号(sn): * 4, id:随机码.若前面的都取不到时,则随机生成一个随机码,需要缓存. * * @param context * @return */ p

  • Android 如何获取设备唯一标识

    一. 先简单总结一下比较常见的几个解决方案的弊端: 1. IMEI Android 10 中官方明确说明第三方应用无法获取到IMEI码:Android 10 中的隐私权变更, Android 10 以下的版本,需要申请READ_PHONE_STATE权限. 2. Android ID Android ID 不具有真正的唯一性, ROOT.刷机.恢复出厂设置.不同签名的应用等都会导致获取的 Android ID 发生改变, 并且不同厂商定制的系统的BUG会导致不同的设备可能会产生相同的 Andro

  • 详解Android获取设备唯一ID的几种方式

    先来看看几种比较单一的方式: IMEI 方式:TelephonyManager.getDeviceId(): 问题 范围:只能支持拥有通话功能的设备,对于平板不可以. 持久性:返厂,数据擦除的时候不彻底,保留了原来的标识. 权限:需要权限:Android.permission.READ_PHONE_STATE bug: 有些厂家的实现有bug,返回一些不可用的数据  Mac地址 ACCESS_WIFI_STATE权限 有些设备没有WiFi,或者蓝牙,就不可以,如果WiFi没有打开,硬件也不会返回

  • Android 获取设备屏幕大小的几种方法总结

    1.通过WindowManager获取 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); System.out.println("heigth : " + dm.heightPixels); System.out.println("width : " + dm.widthPixels); 2.通过Resources获取 Di

  • vue3 微信扫码登录及获取个人信息实现的三种方法

    目录 一.流程: 二.前置条件: 三.具体登录实现 实现方式一: 方式二: 方式三:结合后端获取到二维码 四.登录微信后获取微信中用户头像和昵称 一.流程: 微信提供的扫码方式有两种,分别是: 跳转二维码扫描页面 内嵌式二维码 根据文档我们可以知道关于扫码授权的模式整体流程为: 1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据 code 参数: 2. 通过 code 参数加上 AppID 和AppSecret等,通过 API

  • iOS获取当前时间和当前时间戳的方法

    //获取当前的时间 +(NSString*)getCurrentTimes{ NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; // ----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制 [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; //现在时间,你可以输出来看下是什么格式 NSDate *datenow = [NSDate d

  • 详解IOS判断当前网络状态的三种方法

    在项目中,为了好的用户体验,有些场景必须线判断网络状态,然后才能决定该干嘛.比如视频播放,需要线判断是Wifi还是4G,Wifi直接播放,4G先提示用户.获取网络状态的方法大概有三种: 1. Reachability 这是苹果的官方演示demo中使用到的方法,我们可以到苹果官方文档里下载Demo(点击左上角Download Sample Code 即可下载),然后把Demo里的Reachability.h和.m考到自己项目中,并在Build Phases 的 Link Binary 添加Syst

随机推荐