2015-04-20 55 views
30

Мы работаем над проектом с моими коллегами, который предполагает использование большого количества частного и неофициального кода. Это не предназначен для использования в AppStore.Частный уникальный идентификатор устройства в iOS

Первое и единственное требование у нас есть нет использование джейлбрейк.

Прежде всего, UDID или OpenUDID или любые другие решения не работают здесь, и они не ожидается.

Мы провели много фоновых исследований и испытаний, начиная с попытки программно получить IMEI, ICCID, IMSI и серийный номер. Ни один из вышеперечисленных методов не работает с iOS 7 и выше без джейлбрейка.

Мы также провели несколько месяцев играть с IOKit рамки с использованием знаменитой IOKitBrowser и демпинг все содержимое iOS внутренностей. К сожалению, we discovered, что с iOS 8.3 он прекратил работать.

Мы говорим здесь не о получении UDID или какой-либо другой «основной» вещь, но вообще говоря нам нужен способ, чтобы получить

любой постоянный идентификатор аппаратных средств достаточно уникальный для идентификации устройства, будет сохраняться, несмотря на салфетки устройств и среди различных версий IOS

Этого вопрос не дубликат других (no solutions are found here, например) и ориентирован исключительно частные API,.

Любая помощь будет высоко оценена.

+1

Возможный дубликат [UIDevice uniqueIdentifier Устаревший - Что делать?] (Http://stackoverflow.com/questions/6993325/uidevice-uniqueidentifier-deprecated-what- to-do-now) – Paulw11

+0

Единственный способ получить уникальный идентификатор устройства - через MDM-маршрут - вам нужно установить профиль управления устройством на устройстве, и ваш сервер сможет получить доступ к UDID – Paulw11

+0

@ Paulw11 благодарит за идею, но, к сожалению, это не помогло бы. И наш вопрос не является дубликатом - это все о ** private apis **, а не публичные, в том числе устаревшие. –

ответ

14

После некоторого копания я обнаружил, что все частные API используют libMobileGestalt для получения любых идентификаторов оборудования, которые, в свою очередь, используют IOKit. MobileGestalt проверяет правила песочницы для текущего pid и ищет com.apple.private.MobileGestalt.AllowedProtectedKeys право.

Смотрите ниже код:

signed int __fastcall sub_2EB8803C(int a1, int a2, int a3, int a4) 
{ 
    int v4; // [email protected] 
    int v5; // [email protected] 
    int v6; // [email protected] 
    int v7; // [email protected] 
    int v8; // [email protected] 
    int v9; // [email protected] 
    int v10; // [email protected] 
    int v11; // [email protected] 
    int v12; // [email protected] 
    signed int v13; // [email protected] 
    int v14; // [email protected] 
    char *v15; // [email protected] 
    int v16; // [email protected] 
    int v17; // [email protected] 
    int v18; // [email protected] 
    int v19; // [email protected] 
    signed int v20; // [email protected] 
    int v21; // [email protected] 
    __CFString *v22; // [email protected] 
    int v23; // [email protected] 
    __CFString *v24; // [email protected] 
    int v26; // [sp+8h] [bp-428h]@1 
    char v27; // [sp+10h] [bp-420h]@1 
    int v28; // [sp+414h] [bp-1Ch]@1 

    v26 = a2; 
    v4 = a1; 
    v5 = a3; 
    v6 = a4; 
    v28 = __stack_chk_guard; 
    memset(&v27, 0, 0x401u); 
    v7 = *(_DWORD *)(dword_32260254 + 260); 
    if (!v7) 
    v7 = sub_2EB8047C(65, 2); 
    v8 = ((int (__fastcall *)(int, _DWORD))v7)(v4, "com.apple.private.MobileGestalt.AllowedProtectedKeys"); 
    v9 = v8; 
    if (!v8) 
    goto LABEL_12; 
    v10 = v5; 
    v11 = CFGetTypeID(v8); 
    if (v11 != CFArrayGetTypeID()) 
    { 
    v14 = (int)"/SourceCache/MobileGestalt/MobileGestalt-297.1.14/MobileGestalt.c"; 
    v15 = rindex("/SourceCache/MobileGestalt/MobileGestalt-297.1.14/MobileGestalt.c", 47); 
    v16 = *(_DWORD *)(dword_32260254 + 288); 
    if (v15) 
     v14 = (int)(v15 + 1); 
    if (!v16) 
     v16 = sub_2EB8047C(72, 2); 
    ((void (__fastcall *)(int))v16)(v4); 
    _MGLog(3, v14); 
LABEL_12: 
    v13 = 0; 
    goto LABEL_13; 
    } 
    v12 = CFArrayGetCount(v9); 
    if (CFArrayContainsValue(v9, 0, v12, v26)) 
    v13 = 1; 
    else 
    v13 = sub_2EB7F948(v9, v26, v10, "MGCopyAnswer"); 
LABEL_13: 
    if (!v6) 
    goto LABEL_30; 
    v17 = *(_DWORD *)(dword_32260254 + 288); 
    if (!v17) 
    v17 = sub_2EB8047C(72, 2); 
    v19 = ((int (__fastcall *)(int))v17)(v4); 
    if (v13 != 1) 
    { 
    v21 = *(_DWORD *)v6; 
    if (*(_DWORD *)v6) 
    { 
     v22 = CFSTR(" and IS NOT appropriately entitled"); 
     goto LABEL_22; 
    } 
    v23 = CFStringCreateMutable(0, 0); 
    *(_DWORD *)v6 = v23; 
    sub_2EB7F644(v19, &v27); 
    v24 = CFSTR("pid %d (%s) IS NOT appropriately entitled to fetch %@"); 
    goto LABEL_29; 
    } 
    v20 = MGGetBoolAnswer((int)CFSTR("LBJfwOEzExRxzlAnSuI7eg")); 
    v21 = *(_DWORD *)v6; 
    if (v20 == 1) 
    { 
    if (v21) 
    { 
     v22 = CFSTR(" but IS appropriately entitled; all is good in the world"); 
LABEL_22: 
     CFStringAppendFormat(v21, 0, v22, v18); 
     goto LABEL_30; 
    } 
    v23 = CFStringCreateMutable(0, 0); 
    *(_DWORD *)v6 = v23; 
    sub_2EB7F644(v19, &v27); 
    v24 = CFSTR("pid %d (%s) IS appropriately entitled to fetch %@; all is good in the world"); 
LABEL_29: 
    CFStringAppendFormat(v23, 0, v24, v19); 
    goto LABEL_30; 
    } 
    if (v21) 
    { 
    CFRelease(v21); 
    *(_DWORD *)v6 = 0; 
    } 
    *(_DWORD *)v6 = 0; 
LABEL_30: 
    if (__stack_chk_guard != v28) 
    __stack_chk_fail(__stack_chk_guard - v28); 
    return v13; 
} 

signed int __fastcall sub_2EB88228(int a1, int a2, int a3) 
{ 
    int v3; // [email protected] 
    int v4; // [email protected] 
    int v5; // [email protected] 
    int v6; // [email protected] 
    int v7; // [email protected] 
    signed int result; // [email protected] 
    char v9; // [sp+8h] [bp-420h]@5 
    int v10; // [sp+40Ch] [bp-1Ch]@1 

    v3 = a1; 
    v4 = a3; 
    v10 = __stack_chk_guard; 
    v5 = sandbox_check(); 
    v6 = v5; 
    if (v5) 
    v5 = 1; 
    if (v4 && v5 == 1) 
    { 
    memset(&v9, 0, 0x401u); 
    v7 = CFStringCreateMutable(0, 0); 
    *(_DWORD *)v4 = v7; 
    sub_2EB7F644(v3, &v9); 
    CFStringAppendFormat(v7, 0, CFSTR("pid %d (%s) does not have sandbox access for %@"), v3); 
    } 
    result = 0; 
    if (!v6) 
    result = 1; 
    if (__stack_chk_guard != v10) 
    __stack_chk_fail(result); 
    return result; 
} 

Как описано here, UDID рассчитывается следующим образом:

UDID = SHA1(serial + ECID + wifiMac + bluetoothMac) 

MobileGestalt получает эти значения с помощью IOKit так:

CFMutableDictionaryRef service = IOServiceMatching("IOPlatformExpertDevice"); 
    io_service_t ioservice = IOServiceGetMatchingService(kIOMasterPortDefault, service); 
    CFTypeRef entry = IORegistryEntryCreateCFProperty(ioservice, CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0); 

    const UInt8 * data = CFDataGetBytePtr(entry); 
    CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, data, kCFStringEncodingUTF8); 

Если вы пытаетесь сделать это сами, это не удастся использовать новые правила песочницы в прошивкой 8.3 очень строги и запретить доступ ко всем аппаратным идентификаторам так:

deny iokit-get-properties IOPlatformSerialNumber 

Возможное решение

Похоже, единственный способ, вы можете получить UDID следующая:

  1. Запустите веб-сервер внутри приложения с двумя страницами: нужно вернуть специально созданный профиль MobileConfiguration, а другой должен собирать UDID.Больше информации here, here и here.
  2. Вы открываете первую страницу в Mobile Safari изнутри приложения и перенаправляет ее на Settings.app с просьбой установить профиль конфигурации. После установки профиля UDID отправляется на вторую веб-страницу, и вы можете получить доступ к нему изнутри приложения. (Settings.app имеет все необходимые права и различные правила для песочницы).

Подтвержденные рабочий раствор

Ниже приведен пример, основанный на RoutingHTTPServer:

import UIKit 
import RoutingHTTPServer 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate { 
    var bgTask = UIBackgroundTaskInvalid 
    let server = HTTPServer() 

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
     application.openURL(NSURL(string: "http://localhost:55555")!) 
     return true 
    } 

    func applicationDidEnterBackground(application: UIApplication) { 
     bgTask = application.beginBackgroundTaskWithExpirationHandler() { 
      dispatch_async(dispatch_get_main_queue()) {[unowned self] in 
       application.endBackgroundTask(self.bgTask) 
       self.bgTask = UIBackgroundTaskInvalid 
      } 
     } 
    } 
} 

class HTTPServer: RoutingHTTPServer { 
    override init() { 
     super.init() 
     setPort(55555) 
     handleMethod("GET", withPath: "/") { 
      $1.setHeader("Content-Type", value: "application/x-apple-aspen-config") 
      $1.respondWithData(NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("udid", ofType: "mobileconfig")!)!) 
     } 
     handleMethod("POST", withPath: "/") { 
      let raw = NSString(data:$0.body(), encoding:NSISOLatin1StringEncoding) as! String 
      let plistString = raw.substringWithRange(Range(start: raw.rangeOfString("<?xml")!.startIndex,end: raw.rangeOfString("</plist>")!.endIndex)) 
      let plist = NSPropertyListSerialization.propertyListWithData(plistString.dataUsingEncoding(NSISOLatin1StringEncoding)!, options: .allZeros, format: nil, error: nil) as! [String:String] 

      let udid = plist["UDID"]! 
      println(udid) // Here is your UDID! 

      $1.statusCode = 200 
      $1.respondWithString("see https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/iPhoneOTAConfiguration/ConfigurationProfileExamples/ConfigurationProfileExamples.html") 
     } 
     start(nil) 
    } 
} 

Вот содержимое udid.mobileconfig:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
    <dict> 
     <key>PayloadContent</key> 
     <dict> 
      <key>URL</key> 
      <string>http://localhost:55555</string> 
      <key>DeviceAttributes</key> 
      <array> 
       <string>IMEI</string> 
       <string>UDID</string> 
       <string>PRODUCT</string> 
       <string>VERSION</string> 
       <string>SERIAL</string> 
      </array> 
     </dict> 
     <key>PayloadOrganization</key> 
     <string>udid</string> 
     <key>PayloadDisplayName</key> 
     <string>Get Your UDID</string> 
     <key>PayloadVersion</key> 
     <integer>1</integer> 
     <key>PayloadUUID</key> 
     <string>9CF421B3-9853-9999-BC8A-982CBD3C907C</string> 
     <key>PayloadIdentifier</key> 
     <string>udid</string> 
     <key>PayloadDescription</key> 
     <string>Install this temporary profile to find and display your current device's UDID. It is automatically removed from device right after you get your UDID.</string> 
     <key>PayloadType</key> 
     <string>Profile Service</string> 
    </dict> 
</plist> 

Установка профиля утратит (Я не потрудился реализовать ожидаемый ответ, см. documentation), но приложение получит правильный UDID. И вы также должны sign the mobileconfig.

+1

Никогда не знал, что можно будет создать такую ​​схему, как вы описали. Мы проверим это, спасибо –

+1

После нескольких недель исследований я вернусь, чтобы подтвердить, что все существующие решения требуют запуска скриптов php для сбора данных.Мы настроили локальный сервер iOS и сам профиль. Он устанавливает и даже перенаправляет обратно на наш встроенный сервер, но для него требуется либо скрипт 'php', либо возвращается какой-то файл' p7s', либо он требует «HTTPS» вообще. И я не уверен, что какие-либо из серверных решений знают, как обращаться с 'php'. Я могу открыть новый вопрос с щедростью 500, если бы вы могли помочь. Мы видим, что, вероятно, никто раньше не решал такую ​​задачу раньше, и нам нужна помощь. Спасибо –

+0

@SergiusGee Файл 'p7s' является подписанным plist, который содержит UDID. Я обновил свой ответ с помощью кода, который содержит технику извлечения UDID. – bzz

2

Я не уверен в ваших полных намерениях, но было бы достаточно, чтобы приложение создало и сохранила ваш собственный уникальный идентификатор в приложении при установке? Тогда, возможно, приложение отправит этот идентификатор на сервер и сохранит IP-адрес, из которого он пришел. Возможно, также есть некоторая логика, чтобы иметь телефон приложения домой так часто, чтобы вы могли хранить дополнительные IP-адреса, если они меняются. Очевидно, что это не является надежным, но это может быть началом обходного пути.

+0

Отличная идея, но как вы гарантируете, что динамические IP-адреса в мобильных сетях, которые выбраны случайным образом, не пересекаются раз в то время? И после переустановки приложение создаст новый идентификатор, в то время как мне все равно понадобится тот, и только он отправил меня до –

+0

. Я не могу, поэтому он не является надежным, но этого может быть достаточно в зависимости от ваших намерений. Что вы пытаетесь предотвратить/отслеживать? – Rel

+0

Если EIMI был одним из ваших предыдущих вариантов, можно ли сказать, что все ваши устройства будут мобильными/мобильными? т.е. не ipod touch. – Rel

2

Что об этом: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/#//apple_ref/occ/instp/UIDevice/identifierForVendor

Буквенно-цифровая строка, которая однозначно идентифицирует устройство к поставщику приложения. (только для чтения)

Значение этого свойства тот же для приложений, которые поступают из того же поставщика, работающего на одном устройстве. Другое значение возвращается для приложений на том же устройстве, что и у разных поставщиков, а также для приложений на разных устройствах независимо от поставщика.

С прошивкой 6 и ток в прошивке 8

Это соответствует вашим требованиям:

любого постоянного аппаратного идентификатора достаточно уникального, чтобы идентифицировать устройство, которое будет сохраняться, несмотря на салфетки устройств и среди разные версии iOS

Это задокументировано как уникальное для каждого устройства и постоянное, будь то в магазине приложений или на предприятии.

Обычно поставщик определяется данными, предоставленными магазином приложений. Если приложение не было установлено из магазина приложений (например, корпоративных приложений и приложений, все еще находящихся в разработке), то идентификатор поставщика рассчитывается на основе идентификатора пакета приложения. Предполагается, что идентификатор пакета имеет формат обратного DNS.

+0

Нет, это не настойчиво. Он может быть сброшен вручную, и он изменяется на стирание устройства. –

2

Я не знаю, если коммерческие решения представляют интерес для вас, но проверить http://www.appsflyer.com

Я не аффилированный с ними, но мы использовали их SDK в моем предыдущем работодателе. У них есть технология отпечатков пальцев устройства, которая работает.

Примечание: Если пользователь сбрасывает IDFA, то приложение AppsFlyer увидит это как новое устройство. Тем не менее, и это было некоторое время, поэтому я не могу вспомнить, я думаю, вы можете использовать их SDK, а не использовать AdSupport.framework, и тогда у них не будет доступной для них IDFA. Поэтому я предполагаю, что их отпечатки пальцев на устройстве могут работать.

У них также есть конкуренты, поиск отпечатков пальцев устройства. Отъезд Yozio и branch.io, они оба утверждают, что делают это. Я не использовал их продукт, просто видел их сайты.

+0

Спасибо за отличный совет. Мы проверим его –

+0

Сообщите нам, если работает трюк non IDFA. Если я помню, что их документ был немного неясен в этом. –

+0

Я работал над SDK Branch.io iOS, и я знаю других компаний в космосе. Все просто используют IDFA для неприкосновенности частной жизни. Мы не хотим подвергать наших партнеров приложения рискам с чем-то слишком рискованным. Apple уже случайно отклоняет за неправильное использование коллекции IDFA, поэтому будьте осторожны. –

3

Вы можете попробовать lockdowndAPI напрямую, через libMobileGestalt.dylib.

Header here. Основной код для доступа к UDID должен быть: (вам все равно нужно загрузить dylib)

CFStringRef udid = (CFStringRef)MGCopyAnswer(kMGUniqueDeviceID); 

взятого (& слегка модифицированный) от here.

Для получения дополнительной информации о libMobileGestalt, посмотрите here.

Если это не удается, вы все равно можете попытаться связаться с lockdownd через SSL-разъем (см. here), не знаю, как это работает, но вы можете понять это.

Как вы, возможно, заметили, все это в этом возрасте. По-прежнему стоит попробовать, я думаю.

+0

Ничего себе, это замечательно. Я проверю это, iPad вернется к вам. Спасибо –

+0

Пробовал это с MobileGestalt, также возвращает null. Попытка подключиться к блокировке с помощью lockdown_connect() возвращает null. – gbuzogany

+0

@gbuzogany, вам также необходимо [право на выполнение этой работы] (http://stackoverflow.com/a/27686125/119114), что ограничивает вас джейлбрейковыми устройствами. – Nate

14

Прошу прощения, что, по-видимому, из iOS 8.3, для получения любого уникального идентификатора вам нужен более высокий уровень доступа, чем обычный пользователь.

Без использования каких-либо вещей, только с помощью частных фреймворков, библиотек и запросов ядра, любой запрос к уникальным идентификаторам возвращает null.

Иллюстрируя:

Попытка использовать IOKit:

void *IOKit = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW); 
if (IOKit) 
{ 
    mach_port_t *kIOMasterPortDefault = dlsym(IOKit, "kIOMasterPortDefault"); 
    CFMutableDictionaryRef (*IOServiceMatching)(const char *name) = dlsym(IOKit, "IOServiceMatching"); 
    mach_port_t (*IOServiceGetMatchingService)(mach_port_t masterPort, CFDictionaryRef matching) = dlsym(IOKit, "IOServiceGetMatchingService"); 
    CFTypeRef (*IORegistryEntryCreateCFProperty)(mach_port_t entry, CFStringRef key, CFAllocatorRef allocator, uint32_t options) = dlsym(IOKit, "IORegistryEntryCreateCFProperty"); 
    kern_return_t (*IOObjectRelease)(mach_port_t object) = dlsym(IOKit, "IOObjectRelease"); 

    if (kIOMasterPortDefault && IOServiceGetMatchingService && IORegistryEntryCreateCFProperty && IOObjectRelease) 
    { 
     mach_port_t platformExpertDevice = IOServiceGetMatchingService(*kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); 
     if (platformExpertDevice) 
     { 
      CFTypeRef platformSerialNumber = IORegistryEntryCreateCFProperty(platformExpertDevice, CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0); 
      if (platformSerialNumber && CFGetTypeID(platformSerialNumber) == CFStringGetTypeID()) 
      { 
       serialNumber = [NSString stringWithString:(__bridge NSString *)platformSerialNumber]; 
       CFRelease(platformSerialNumber); 
      } 
      IOObjectRelease(platformExpertDevice); 
     } 
    } 
    dlclose(IOKit); 
} 

терпит неудачу. Причина: IOPlatformSerialNumber недоступен. Многие другие запросы работают нормально.

Попытка использовать Mach вызовы, чтобы получить сетевые адаптеры, HW идентификаторы:

int   mib[6], 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; 
if ((mib[5] = if_nametoindex("en0")) == 0) { 
    perror("if_nametoindex error"); 
    exit(2); 
} 

if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { 
    perror("sysctl 1 error"); 
    exit(3); 
} 

if ((buf = malloc(len)) == NULL) { 
    perror("malloc error"); 
    exit(4); 
} 

if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { 
    perror("sysctl 2 error"); 
    exit(5); 
} 

ifm = (struct if_msghdr *)buf; 
sdl = (struct sockaddr_dl *)(ifm + 1); 
ptr = (unsigned char *)LLADDR(sdl); 
printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *ptr, *(ptr+1), *(ptr+2), 
     *(ptr+3), *(ptr+4), *(ptr+5)); 

терпит неудачу. Причина: возвращает 02:00:00:00:00:00 для любого сетевого адаптера.

Попытка подключения к lockdownd:

void *libHandle = dlopen("/usr/lib/liblockdown.dylib", RTLD_LAZY); 
if (libHandle) 
{ 
    lockdown_connect = dlsym(libHandle, "lockdown_connect"); 
    lockdown_copy_value = dlsym(libHandle, "lockdown_copy_value"); 

    id connection = lockdown_connect(); 
    NSString *kLockdownDeviceColorKey 
    NSString *color = lockdown_copy_value(connection, nil, kLockdownDeviceColorKey); 
    NSLog(@"color = %@", color); 
    lockdown_disconnect(connection); 

    dlclose(libHandle); 
} 
else { 
    printf("[%s] Unable to open liblockdown.dylib: %s\n", 
      __FILE__, dlerror()); 
} 

терпит неудачу. Причина: lockdown_connect() не работает, возвращается null.

Попытка использовать libMobileGestalt:

void *libHandle = dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_LAZY); 
if (libHandle) 
{ 
    MGCopyAnswer = dlsym(libHandle, "MGCopyAnswer"); 

    NSString* value = MGCopyAnswer(CFSTR("SerialNumber")); 
    NSLog(@"Value: %@", value); 
    CFRelease(value); 
} 

терпит неудачу. Причина: запросы на получение уникальных идентификаторов null. Любой другой запрос работает нормально.

Мое предложение - использовать некоторую технику эскалации привилегий, чтобы получить доступ суперпользователя, а затем запустить любой из перечисленных здесь методов, чтобы получить свойство.

Также распространите исследование на liblockdown. Если он доступен на уровне пользователя (с чем-то другим, кроме lockdown_connect), возможно, это будет возможно прочитать эти вещи.

+0

Вау, это, безусловно, удивительное исследование! Однако, как насчет того, что мы не ищем UDID как таковой, а для некоторых других идентификаторов оборудования, в основном ** любой ** уникальный идентификатор оборудования, например дата изготовления, который идеально подойдет. Есть идеи по этому поводу? –

+0

Я искал уникальный идентификатор, а не только UDID. По-видимому, они отображали ЛЮБОЙ уникальный идентификатор устройства и покрывали его. В iOS 8.3 появилось [много] (http://www.intego.com/mac-security-blog/apples-colossal-ios-8-3-update-kills-58-ios-security-bugs/) [обновления для системы безопасности ] (https://support.apple.com/en-us/HT204661), поэтому я думаю, что это было ориентировано на безопасность, потому что это не принесло ничего другого. Я искал идентификаторы сетевого оборудования, серийные номера, даты производства, младший/основной идентификатор Bluetooth, IMEI, идентификаторы основной полосы, все, что захоронено. – gbuzogany

1

На самом деле я не знаю, как это решение полезно или нет. но после удаления поддержки UDID. Я управляю уникальной идентификацией устройства следующим образом. с помощью Vendor ID. Вот что мы сделали.

В качестве начального, пока приложение будет работать, я проверю, что погода vendor ID для конкретного приложения - stored in key chain or not. если он не сохранен, тогда я сохраню это vendor ID в key chain. так что второй раз, когда мое приложение снова проверит, что идентификатор поставщика погоды для конкретного приложения хранится не в цепочке ключей. если они сохранены, то принесите его из цепочки ключей и выполните действие на том же уровне в соответствии с требованием. so here alway vendor ID is unique for device.

Вот шаги, которые мы сохраняем уникальность устройства с помощью vendor ID.

Этап 1: Включите Lockbox в свой проект. что поможет вам stored/retrived ID поставщика in/from брелок.

Шаг 2: Вот код, который выполняет действие checking vendor ID и retrieving vendor ID из брелка.

-(NSString*)getidentifierForVendor{ 
    NSString *aStrExisting = [Lockbox stringForKey:[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleIdentifierKey]]; 

    if (aStrExisting == Nil) { 
     NSString *aVendorID = [[[UIDevice currentDevice]identifierForVendor]UUIDString]; 
     aStrExisting=aVendorID; 
     [Lockbox setString:aVendorID forKey:[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleIdentifierKey]]; 
     return aVendorID; 
    }else{ 
     return aStrExisting; 
    } 

С помощью вышеуказанных шагов вы всегда получаете уникальность устройства. потому что цепочка ключей никогда не удаляется. он всегда обновляется.

Надеется, что это поможет вам ...

+0

И на устройстве вытереть идентификатор поставщика будет другим. Вот почему мы не можем его использовать –

+0

@SergiusGee, знаю, но сначала нужно проверить, что если идентификатор поставщика для определенного «ИД приложения» присутствует в цепочке ключей или что-то еще. если он присутствует, нам не нужно использовать новый идентификатор поставщика. просто выбрал начальный идентификатор поставщика из ключевой цепи. поэтому он станет уникальным для приложения -> устройства. –

+0

и что происходит, когда брелок стирается? Это совершенно новый идентификатор, тогда –

1

Вы позволили спросить пользователь для их MSISDN-х? (международные номера телефонов) Как то, что делает whatsApp, когда вы впервые входите в систему с их помощью, с помощью SMS-кода, отправленного пользователю msisdn. Если вы знаете MSISDN своих пользователей, вы можете сохранить их в своей базе данных на сервере и разрешить только зарегистрированный и указанный вами msisdn список и использовать ваши службы. Если вы хотите быть более безопасным, вы можете чаще отправлять SMS-сообщения, но есть способ понять изменение SIM-карты (это касается использования t-mobile и europe, я думаю) из APP, чтобы пользователь не мог одурачить вас ввод SMS для другого MSISDN, а затем переход на его/ее реальную SIMIS-карту MSISDN.

MSISDN уникальны по всему миру, и они обеспечены операторами связи, поэтому я предполагаю, что это решение строго безопасно. Что ты говоришь?удачи

обновление: на самом деле, внимательно прочитав свой вопрос, я думаю, вы не хотите, чтобы пользователь входил в систему с любой информацией? если тот случай извините за неправильный ответ:/

примечание: почему не могу использовать

[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString] 

рекламный идентификатор является уникальным для устройства и постоянного я думаю. Я не знаю, можете ли вы использовать его конфиденциально, но ..

Смежные вопросы