Apple解决方案

 1、使用CFUUIDCreateString(NULL, CFUUIDCreate(NULL))生成UUID

 2、将UUID缓存在本地,sqlite或plist。使用时取出

 评价:

 坑爹!这种方式每次UUID生成一次都不一样,如果产品被fuck out of device,再装载会导致两次UUID不一致。这个方案明显适用范围狠窄啊亲。于是乎各路妖魔鬼怪开始了各种解决方案。

 

 方案一:(Mac地址+bundle_id)

 1、获取本地mac地址和应用bundle_id

 2、将mac+bundle_id进行散列运算获得机器+应用的唯一标识

 3、只将mac进行散列运算获得机器的唯一标识

 评价:

 狠好的解决方案,如果没有2B的联通搅局,这个方案可以说完美了,取wifi的mac地址除,非你修机器把wifi换掉。但是亲,中国曾经出过太监版3GS,泥马,这是一种怎样的考量删除了wifi啊。这种拍脑袋的做法就是当局的2B,联通跟着傻B。whatthe fuck!你说还有其他方案不,不要依赖硬件?

 

 方案二:(推送token+bundle_id)

 1、应用中增加推送用来获取token

 2、获取应用bundle_id

 3、根据token+bundle_id进行散列运算

 评价:

 apple push token保证设备唯一,但必须有网络情况下才能工作,该方法不依赖于设备本身,但依赖于apple push。加上一定的业务逻辑可以解决大部分情景。

 

 方案三:openUUID

 我不知道是谁想出来的,而且还有很多博客里都说这个是解决方案,还弄的长篇大论,我实在看不出来这个方案和apple提供的UUID方案有什么不同。这种方案各种无解,删除应用后还是没法解决问题啊亲。

 

这里以第一种方案做设置 :

 

根据设备的Mac地址和系统唯一标示符BundleIdentifier获取设备唯一识别符

第一步:获取设备Mac地址,并转化为传统的Mac地址格式;

第二步:进行散列hash处理,即进行MD5信息加密,目的是用户个人隐私数据不能进行明文传播;

第三步:返回设备唯一识别符,保存到服务器端,作为唯一标示符区别注册用户。



具体操作过程为:

1.创建文件

这里创建两个文件,这两个都包括.h和.m 文件,文件名分别为:NSString+MD5sAddition和UIDevice+BundleIdentifier,其创建步骤如果下,找到文件创建模板如图1.1所示:

iOS硬件标识 apple从iphone手机硬件标识_IOS开发

图1.1

创建该格式的文件,选择NSString格式和UIDevice两种格式,分别创建文件如图1.2所示,创建结束后生成的文件如图1.3所示



iOS硬件标识 apple从iphone手机硬件标识_bundle_02


图1.2  选中需要的文件格式


iOS硬件标识 apple从iphone手机硬件标识_iPhone技术_03

图1.3 生成后文件

2.代码编写

文件创建完后,编写代码,首先理清思路,即Mac地址不能明文传递,必须进行加密处理,故编写加密代码,加密算法主要是使用MD5加密技术进行加密。

在NSString+MD5sAddition.h文件中声明对外方法,方法名为:stringFromMD5s;返回值为字符串类型,如图2.1所示:


iOS硬件标识 apple从iphone手机硬件标识_IOS开发_04

图2.1  声明加密方法

 

具体实现需要在.m文件中进行,需要引入一些命名空间,具体代码如下所示:

//调用系统内部文件,获取获取硬件信息

#import<CommonCrypto/CommonDigest.h>

@implementation

-(NSString

{

//若为空则返回

if (self==nil||[self length]==0) {

return nil;

    }

//将传入的信息进行UTF8格式化

const char *value=[self UTF8String];

   

//16位加密

unsigned char outPutBuffer[CC_MD5_DIGEST_LENGTH];

   

//将传入的字符串value加密,并以固定长度的outPutBuffer输出

CC_MD5(value, strlen(value), outPutBuffer);

   

NSMutableString *outPutString=[[NSMutableString alloc]initWithCapacity:CC_MD5_DIGEST_LENGTH*2];

for (NSInteger count=0;count<CC_MD5_DIGEST_LENGTH; count++) {

//向可变字符串中追加字节信息

appendFormat:@"%02x",outPutBuffer[count]];

    }

//返回加密后的字符串

return [outPutString autorelease];

}

@end



下面是在UIDevice+BundleIdentifier文件中进行的操作,在.h文件中声明两个对外的方法,如图2.2所示,声明两个对外的公共方法

iOS硬件标识 apple从iphone手机硬件标识_bundle_05



.m文件中代码如下所示:

/*

    本类说明:根据设备的Mac地址和系统唯一标示符BundleIdentifier获取设备唯一识别符

            第一步:获取设备Mac地址,并转化为传统的Mac地址格式;

            第二步:进行散列hash处理,即进行MD5信息加密,目的是用户个人隐私数据不能进行明文传播;

            第三步:返回设备唯一识别符,保存到服务器端,作为唯一标示符区别注册用户。

    创建时间:2012年11月02日

    写   作:张志轩

*/
 
#import"UIDevice+BundleIdentifier.h"
 
//MD5加密文件调用
#import"NSString+MD5sAddition.h"
 
//引用底层信息类
#include<sys/socket.h>
#include<sys/sysctl.h>
#include<net/if.h>
#include<net/if_dl.h>
 
@interface
//获取Mac地址--本类私有方法
-(NSString
@end
 
@implementation
-(NSString
{
//设置参数
//Mac地址为6组共12个字符,格式为:XX:XX:XX:XX:XX:XX
int                 mib[6];
size_t
char
unsigned char
struct if_msghdr
struct sockaddr_dl
    
    
/*
     设置信息资源库
     */
 
//请求网络子系统
0]=CTL_NET;
    
//路由表信息
1]=AF_ROUTE;
    
2]=0;
    
//链路层信息
3]=AF_LINK;
    
//配置端口信息
4]=NET_RT_IFLIST;
    
//判断En0地址是否存在,除联通3GS太监外,都存在
if ((mib[5]=if_nametoindex("en0"))==0) {
return  NULL;
    }
    
//获取数据的大小
if (sysctl(mib, 6, NULL,&len, NULL, 0)<0) {
return  NULL;
    }
    
//分配内存的基础上调用
if ((buf=malloc(len))==NULL) {
return  NULL;
    }
    
//获取系统信息,存储在缓冲区
if ((sysctl(mib, 6, buf, &len, NULL, 0))<0) {
free(buf);
return  NULL;
    }
    
//获取接口电气性结构
struct  if_msghdr
struct  sockaddr_dl *)(ifm+1);
unsigned  char *)LLADDR(sdl);
    
//获取Mac地址信息:读取字符数组到一个字符串对象,设置为传统的Mac地址,即XX:XX:XX:XX:XX:XX
NSString *outString=[NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", 
1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
//返回Mac地址信息
return
}
/*
     对外公开方法
     */
#pragmamark -
#pragmamark - 通过Mac地址获取设备唯一标示符
-(NSString
{
    
//获取Mac地址
NSString *macAddress=[[UIDevice currentDevice] macAddress];
//对Mac地址进行加密
NSString *uniquenessDeviceIdentifier=[macAddress stringFromMD5s];
//返回加密后的Mac地址
return
}
 
#pragmamark -
#pragmamark - 将mac+bundle_id进行散列运算获得机器+应用的唯一标识
-(NSString
{
//获取Mac地址
NSString *macAddress=[[UIDevice currentDevice] macAddress];
//获取BundleIdentifier标示符
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
//组合信息
NSString *hashStringToMacAndIdentifier=[NSString stringWithFormat:@"%@%@",macAddress,bundleIdentifier];
//进行加密
NSString *uniquenessDeviceIdentifier=[hashStringToMacAndIdentifier stringFromMD5s];
//返回加密后唯一标示符
return
}
@end

3.获取用户设备唯一标示符

在调用文件中引入UIDevice+BundleIdentifier.h",如图3.1所示,

iOS硬件标识 apple从iphone手机硬件标识_Mac_06

图3.1 文件引用,获取唯一标示符

 

下面是在某一方法中获取这个用户设备唯一标示符,如下代码所示:

//通过MacAddress和BundleIdentifier,获取用户设备唯一标示符
NSString *userUniquenessIdentifierByMacAddressAndBundleIdentifier=[NSString stringWithFormat:@"%@",[[UIDevice currentDevice]uniquenessDeviceIdentifierByMacAddressAndBundleIdentifier]];
//通过MacAddress,获取用户设备唯一标示符
NSString *userUniquenessIdentifierByMacAddress=[NSString stringWithFormat:@"%@",[[UIDevice currentDevice]uniquenessDeviceIdentifierByMacAddress]];
CheHuiLog(@"userUniquenessIdentifierByMacAddressAndBundleIdentifieris %@",userUniquenessIdentifierByMacAddressAndBundleIdentifier);
CheHuiLog(@"userUniquenessIdentifierByMacAddressis %@",userUniquenessIdentifierByMacAddress);

打印结果如图3.2所示

iOS硬件标识 apple从iphone手机硬件标识_bundle_07

图3.2             唯一标示符打印结果