在iOS中获取设备ID或Mac地址

29

我有一个使用rest与服务器通信的应用程序,我想获取iPhone的MAC地址或设备ID进行唯一性验证,如何实现?


2
这是这些问题的副本:https://dev59.com/SHRB5IYBdhLWcg3wQVSV,https://dev59.com/hEjSa4cB1Zd3GeqPDCpN - Brad Larson
6个回答

41

[[UIDevice currentDevice] uniqueIdentifier]保证对于每个设备都是唯一的。


22
对于那些刚接触这个问题的人,需要知道UDID API在iOS 5中已被弃用。要获取一个唯一标识符,您需要使用iPhone的MAC地址。请注意,MAC地址只是设备特定的标识符,并不像UDID那样可以在应用程序之间共享。 - Di Wu
@diwup,MAC地址是否会因用户使用蜂窝网络或Wi-Fi网络而改变?还是在这两种类型的网络接口中都相同? - Crashalot
什么是非废弃的替代方案? - Nicolas Henin
2
在iOS 6及以上版本中,请使用identifierForVendor代替,它返回NSUUID对象。 - Sam
这是一篇关于替代方案的好文章:http://www.doubleencore.com/2013/04/unique-identifiers/ - Federico

40

uniqueIdentifier(在iOS 5.0中已弃用。相反,请创建一个特定于您的应用程序的唯一标识符。)

文档建议使用CFUUIDCreate而不是[[UIDevice currentDevice] uniqueIdentifier]

因此,以下是如何在您的应用程序中生成唯一ID的方法

CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
NSString *uuidString = (NSString *)CFUUIDCreateString(NULL,uuidRef);

CFRelease(uuidRef);

请注意,您必须将uuidString保存在用户默认设置或其他位置,因为无法再次生成相同的uuidString。
您可以使用UIPasteboard存储生成的uuid。如果应用程序被删除并重新安装,则可以从UIPasteboard中读取旧的uuid。设备擦除时将清除剪贴板。
在iOS 6中,他们引入了NSUUID Class,该类旨在创建UUID字符串。
此外,在iOS 6中添加了@property(nonatomic, readonly, retain) NSUUID *identifierForVendorUIDevice类中。
这个属性的值对于来自同一供应商且在同一设备上运行的应用程序是相同的。对于来自不同供应商的同一设备上的应用程序以及不同设备上的应用程序,将返回不同的值。
如果应用程序在后台运行,并且在设备重新启动后用户第一次解锁设备之前,此属性的值可能为nil。如果值为nil,请等待并稍后再次获取该值。
在iOS 6中,您还可以使用AdSupport.framework中的ASIdentifierManager类。在那里,您可以使用
@property(nonatomic, readonly) NSUUID *advertisingIdentifier

与UIDevice的identifierForVendor属性不同,所有供应商都将返回相同的值。该标识符可能会更改——例如,如果用户擦除设备,则不应将其缓存。
如果应用程序在后台运行且在设备重新启动后用户第一次解锁设备之前,则此属性的值可能为nil。如果值为nil,请稍后再获取该值。
请注意,广告标识符advertisingIdentifier可能会返回00000000-0000-0000-0000-000000000000,因为iOS存在一个错误。相关问题:广告标识符和identifierForVendor返回“00000000-0000-0000-0000-000000000000”

18

你可以使用以下方法获取Mac地址

#import <Foundation/Foundation.h>

@interface MacAddressHelper : NSObject

+ (NSString *)getMacAddress;

@end

实现

#import "MacAddressHelper.h"
#import <sys/socket.h>
#import <sys/sysctl.h>
#import <net/if.h>
#import <net/if_dl.h>

@implementation MacAddressHelper

+ (NSString *)getMacAddress
{
  int                 mgmtInfoBase[6];
  char                *msgBuffer = NULL;
  size_t              length;
  unsigned char       macAddress[6];
  struct if_msghdr    *interfaceMsgStruct;
  struct sockaddr_dl  *socketStruct;
  NSString            *errorFlag = NULL;

  // Setup the management Information Base (mib)
  mgmtInfoBase[0] = CTL_NET;        // Request network subsystem
  mgmtInfoBase[1] = AF_ROUTE;       // Routing table info
  mgmtInfoBase[2] = 0;              
  mgmtInfoBase[3] = AF_LINK;        // Request link layer information
  mgmtInfoBase[4] = NET_RT_IFLIST;  // Request all configured interfaces

  // With all configured interfaces requested, get handle index
  if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0) 
    errorFlag = @"if_nametoindex failure";
  else
  {
    // Get the size of the data available (store in len)
    if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0) 
      errorFlag = @"sysctl mgmtInfoBase failure";
    else
    {
      // Alloc memory based on above call
      if ((msgBuffer = malloc(length)) == NULL)
        errorFlag = @"buffer allocation failure";
      else
      {
        // Get system information, store in buffer
        if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
          errorFlag = @"sysctl msgBuffer failure";
      }
    }
  }
  // Befor going any further...
  if (errorFlag != NULL)
  {
    NSLog(@"Error: %@", errorFlag);
    return errorFlag;
  }
  // Map msgbuffer to interface message structure
  interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
  // Map to link-level socket structure
  socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);  
  // Copy link layer address data in socket structure to an array
  memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);  
  // Read from char array into a string object, into traditional Mac address format
  NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", 
                                macAddress[0], macAddress[1], macAddress[2], 
                                macAddress[3], macAddress[4], macAddress[5]];
  //NSLog(@"Mac Address: %@", macAddressString);  
  // Release the buffer memory
  free(msgBuffer);
  return macAddressString;
}

@end

使用:

NSLog(@"MAC address: %@",[MacAddressHelper getMacAddress]);

获取MAC地址需要很多工作。 - tybro0103
1
使用Mac地址是否合法?如果UUID是隐私漏洞,那么Mac地址可能会更大的漏洞。 - AlfeG
1
这个 MAC 地址是属于哪个接口的?WiFi?3G? - Vame
2
自从iOS7以后,这个功能不再起作用。正如iOS 7的发布说明所述:两个低级网络API曾经返回MAC地址,现在返回固定值02:00:00:00:00:00。涉及到的API是sysctl(NET_RT_IFLIST)和ioctl(SIOCGIFCONF)。使用MAC地址值的开发人员应该迁移到诸如-[UIDevice identifierForVendor]之类的标识符。此更改影响在iOS 7上运行的所有应用程序。Objective-C Runtime 注释 - jules
@Nathan Sakoetoe:我得到了02:00:00:00:00:00的Mac地址。在iOS 8中有没有其他解决方案来获取正确的Mac地址? - Chaaruu Jadhav

5
请使用以下内容:
NSUUID *id = [[UIDevice currentDevice] identifierForVendor];
NSLog(@"ID: %@", id);

4

-10

在这里,我们可以使用Asp.net C#代码找到IOS设备的MAC地址...

.aspx.cs

-
 var UserDeviceInfo = HttpContext.Current.Request.UserAgent.ToLower(); // User's Iphone/Ipad Info.

var UserMacAdd = HttpContext.Current.Request.UserHostAddress;         // User's Iphone/Ipad Mac Address



  GetMacAddressfromIP macadd = new GetMacAddressfromIP();
        if (UserDeviceInfo.Contains("iphone;"))
        {
            // iPhone                
            Label1.Text = UserDeviceInfo;
            Label2.Text = UserMacAdd;
            string Getmac = macadd.GetMacAddress(UserMacAdd);
            Label3.Text = Getmac;
        }
        else if (UserDeviceInfo.Contains("ipad;"))
        {
            // iPad
            Label1.Text = UserDeviceInfo;
            Label2.Text = UserMacAdd;
            string Getmac = macadd.GetMacAddress(UserMacAdd);
            Label3.Text = Getmac;
        }
        else
        {
            Label1.Text = UserDeviceInfo;
            Label2.Text = UserMacAdd;
            string Getmac = macadd.GetMacAddress(UserMacAdd);
            Label3.Text = Getmac;
        }

.class文件

public string GetMacAddress(string ipAddress)
    {
        string macAddress = string.Empty;
        if (!IsHostAccessible(ipAddress)) return null;

        try
        {
            ProcessStartInfo processStartInfo = new ProcessStartInfo();

            Process process = new Process();

            processStartInfo.FileName = "arp";

            processStartInfo.RedirectStandardInput = false;

            processStartInfo.RedirectStandardOutput = true;

            processStartInfo.Arguments = "-a " + ipAddress;

            processStartInfo.UseShellExecute = false;

            process = Process.Start(processStartInfo);

            int Counter = -1;

            while (Counter <= -1)
            {                  
                    Counter = macAddress.Trim().ToLower().IndexOf("mac address", 0);
                    if (Counter > -1)
                    {
                        break;
                    }

                    macAddress = process.StandardOutput.ReadLine();
                    if (macAddress != "")
                    {
                        string[] mac = macAddress.Split(' ');
                        if (Array.IndexOf(mac, ipAddress) > -1)                                
                        {
                            if (mac[11] != "")
                            {
                                macAddress = mac[11].ToString();
                                break;
                            }
                        }
                    }
            }
            process.WaitForExit();
            macAddress = macAddress.Trim();
        }

        catch (Exception e)
        {

            Console.WriteLine("Failed because:" + e.ToString());

        }
        return macAddress;

    }

尝试改善代码格式 - 如您所见,效果并不完全成功 ;-) 请编辑和改进。 - kleopatra
4
这个问题与C#无关,而是涉及到Objective-C和苹果SDK! 错误回答-1。 - jAC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接