iPhone通过Mac地址生成设备唯一标示符

来源:互联网 发布:au录音软件安装 编辑:程序博客网 时间:2024/05/16 09:43

Apple解决方案

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

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

 评价:

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

 

 方案一:(Mac地址+bundle_id

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

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

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

 评价:

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

 

 方案二:(推送tokenbundle_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所示:

图1.1

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




图1.2  选中需要的文件格式



图1.3 生成后文件

2.代码编写

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

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



图2.1  声明加密方法

 

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

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

#import<CommonCrypto/CommonDigest.h>

@implementation NSString (MD5sAddition)

-(NSString *)stringFromMD5s

{

    //若为空则返回

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

        return nil;

    }

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

    const char *value=[selfUTF8String];

   

    //16位加密

    unsigned char outPutBuffer[CC_MD5_DIGEST_LENGTH];

   

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

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

   

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

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

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

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

    }

    //返回加密后的字符串

    return [outPutString autorelease];

}

@end


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



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

/*

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

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

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

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

    创建时间:20121102

      作:张志轩

 */

 

#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 UIDevice (Private)

//获取Mac地址--本类私有方法

-(NSString *)macAddress;

@end

 

@implementation UIDevice (BundleIdentifier)

-(NSString *)macAddress

{

    //设置参数

    //Mac地址为6组共12个字符,格式为:XX:XX:XX:XX:XX:XX

    int                 mib[6];

    size_t              len;

    char                *buf;

    unsigned char      *ptr;

    struct if_msghdr    *ifm;

    struct sockaddr_dl  *sdl;

   

   

    /*

     设置信息资源库

     */

 

    //请求网络子系统

    mib[0]=CTL_NET;

   

    //路由表信息

    mib[1]=AF_ROUTE;

   

    mib[2]=0;

   

    //链路层信息

    mib[3]=AF_LINK;

   

    //配置端口信息

    mib[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;

    }

   

    //获取接口电气性结构

    ifm=(struct if_msghdr *)buf;

    sdl=(struct sockaddr_dl *)(ifm+1);

    ptr=(unsigned char *)LLADDR(sdl);

   

    //获取Mac地址信息:读取字符数组到一个字符串对象,设置为传统的Mac地址,即XX:XX:XX:XX:XX:XX

    NSString *outString=[NSStringstringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",

                         *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];

    //返回Mac地址信息

    return outString;

}

    /*

     对外公开方法

     */

#pragmamark -

#pragmamark - 通过Mac地址获取设备唯一标示符

-(NSString *)uniquenessDeviceIdentifierByMacAddress

{

   

    //获取Mac地址

    NSString *macAddress=[[UIDevicecurrentDevice] macAddress];

    //Mac地址进行加密

    NSString *uniquenessDeviceIdentifier=[macAddressstringFromMD5s];

    //返回加密后的Mac地址

    return uniquenessDeviceIdentifier;

}

 

#pragmamark -

#pragmamark - mac+bundle_id进行散列运算获得机器+应用的唯一标识

-(NSString *)uniquenessDeviceIdentifierByMacAddressAndBundleIdentifier

{

    //获取Mac地址

    NSString *macAddress=[[UIDevicecurrentDevice] macAddress];

    //获取BundleIdentifier标示符

    NSString *bundleIdentifier = [[NSBundlemainBundle] bundleIdentifier];

    //组合信息

    NSString *hashStringToMacAndIdentifier=[NSStringstringWithFormat:@"%@%@",macAddress,bundleIdentifier];

    //进行加密

    NSString *uniquenessDeviceIdentifier=[hashStringToMacAndIdentifierstringFromMD5s];

    //返回加密后唯一标示符

    return uniquenessDeviceIdentifier;

}

@end

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

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


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

 

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

    //通过MacAddressBundleIdentifier,获取用户设备唯一标示符

    NSString *userUniquenessIdentifierByMacAddressAndBundleIdentifier=[NSStringstringWithFormat:@"%@",[[UIDevicecurrentDevice]uniquenessDeviceIdentifierByMacAddressAndBundleIdentifier]];

    //通过MacAddress,获取用户设备唯一标示符

    NSString *userUniquenessIdentifierByMacAddress=[NSStringstringWithFormat:@"%@",[[UIDevicecurrentDevice]uniquenessDeviceIdentifierByMacAddress]];

    CheHuiLog(@"userUniquenessIdentifierByMacAddressAndBundleIdentifieris %@",userUniquenessIdentifierByMacAddressAndBundleIdentifier);

    CheHuiLog(@"userUniquenessIdentifierByMacAddressis %@",userUniquenessIdentifierByMacAddress);

打印结果如图3.2所示

图3.2             唯一标示符打印结果