Подтвердить что ты не робот

Уникальная идентификация пользователя iOS

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

Но мне интересно, возможно ли это. Есть ли что-нибудь, что я могу использовать, чтобы однозначно идентифицировать пользователя? Очень маловероятно, что я могу узнать пользовательский идентификатор Apple. Кроме того, идентификатор устройства однозначно идентифицирует устройство, а не пользователя, поэтому было бы бесполезно, если у пользователя больше устройств...

Есть ли что-нибудь еще, что я могу использовать?

О конфиденциальности - я не хочу ничего узнавать позади пользователя. У меня нет абсолютно никаких проблем с запросом пользователя на доступ к их информации (и если есть API, который предоставляет мне эту информацию, было бы здорово, если API сам это попросит). Как сказал сам Стив Джобс, это то, что касается конфиденциальности - заставляя приложения запрашивать у пользователя разрешение, прежде чем что-либо делать с их личными данными.

4b9b3361

Ответ 1

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

Конечным результатом является случайный UUID (ничего, что фактически идентифицирует пользователя), который отличается для каждого пользователя, но будет иметь одинаковое значение для нескольких устройств, зарегистрированных в одной учетной записи iTunes.

Мы определяем поле в нашем iCloud KV Store, пусть оно называется userID. Когда приложение запускается, мы сначала проверяем userID. Если это так, то у нас все настроено с нашим уникальным идентификатором. Если нет, то это первый раз, когда мы запускаем этого пользователя. Мы генерируем случайный UUID и сохраняем его в KV Store под userID. Это все, что нужно сделать.

Наш опыт показывает, что этот UUID уникален для каждой учетной записи iTunes. Если ваши конечные пользователи используют общий доступ к семье, этим учетным записям будут назначаться разные UUID (что может быть или не быть желательным, но вы ничего не можете с этим поделать). Любое количество устройств, запущенных под одной и той же учетной записью iTunes, увидят один и тот же UUID.

Этот подход является абсолютно законным и должен быть одобрен Apple без каких-либо проблем.

Очевидно, что вы должны включить iCloud Key-Value store в Xcode в разделе "Возможности", просто включите iCloud Switch.

Вот простой класс, который реализует эту концепцию в Objective-C:

@implementation EEUserID

+ (NSUUID *) getUUID
{
    NSUUID *uuid = nil;
    NSString *uuidString = [[NSUbiquitousKeyValueStore defaultStore] stringForKey: @"EEUserID"];
    if (uuidString == nil)
    {
        // This is our first launch for this iTunes account, so we generate random UUID and store it in iCloud:
        uuid = [NSUUID UUID];
        [[NSUbiquitousKeyValueStore defaultStore] setString: uuid.UUIDString forKey: @"EEUserID"];
        [[NSUbiquitousKeyValueStore defaultStore] synchronize];
    }
    else
    {
        uuid = [[NSUUID alloc] initWithUUIDString: uuidString];
    }

    return uuid;
}

+ (NSString *) getUUIDString
{
    NSUUID *uuid = [self getUUID];
    if (uuid != nil)
        return uuid.UUIDString;
    else
        return nil;
}

+ (void) load
{
    // get changes that might have happened while this
    // instance of your app wasn't running
    [[NSUbiquitousKeyValueStore defaultStore] synchronize];
}

@end

И для заголовочного файла:

#import <Foundation/Foundation.h>

@interface EEUserID : NSObject

+ (NSUUID *) getUUID;
+ (NSString *) getUUIDString;

@end

Чтобы использовать, все, что вам нужно сделать, это вызвать:

NSString *uniqueIDForiTunesAccount = [EEUserID getUUIDString];

Наслаждаться.

Ответ 2

Создайте UUID с помощью этого:

NSString *UUID() {
    CFUUIDRef cfuuid = CFUUIDCreate(NULL); 
    NSString *uuid =  (__bridge_transfer NSString *)CFUUIDCreateString(NULL, cfuuid); 
    CFRelease(cfuuid);
    return uuid;
}

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

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

Удачи!

Дополнение:

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

uuid = UUID();
[keychainItemWrapper setObject:uuid forKey:(__bridge_transfer id)kSecAttrAccount];
NSString *pass_token = randomString(10);
[keychainItemWrapper setObject:pass_token forKey:(__bridge_transfer id)kSecValueData];

Обратите внимание, что все это можно сделать без ввода пользователем.

Update:

MCSMKeychainItem имеет отличное решение для создания и хранения UUID с помощью [MCSMApplicationUUIDKeychainItem applicationUUID]. Библиотека также имеет [MCSMGenericKeychainItem genericKeychainItemWithService:service username:username password:password]. Вместе эти функции заботятся обо всем, что упоминалось выше. Простота установки с CocoaPods тоже.

Ответ 3

Раду

Отличный вопрос. Мы решили проблему, которую вы описали, интегрируя Urban Airship (urbanairship.com) в наши приложения. Urban Airship предлагает набор функций для поддержки покупок в приложениях, проверки поступления, восстановления подписки, доставки контента и уведомления Apple Push.

Одной из замечательных особенностей Urban Airship является способность идентифицировать "пользователя", а не устройство, а "пользователь" по электронной почте. Это не действительно рекламируемая "функция"... скорее побочный продукт его предполагаемой функциональности.

Вот что мы нашли и как мы можем использовать Urban Airship для решения вашей проблемы.

Когда пользователь устанавливает ваше приложение с интегрированным в него Urban Airship, UA каким-то образом генерирует UDID-подобный номер, который на данный момент просто идентифицирует устройство.

Однако, если вы используете компоненты восстановления подписки Urban Airship, вы можете ввести адрес электронной почты пользователя. Как только пользователь вводит свой адрес электронной почты на первом устройстве... этот сгенерированный идентификатор становится их основным методом идентификации пользователя и связан с этим адресом электронной почты. Когда они вводят свой адрес электронной почты на последующих устройствах, Urban Airship инициирует процесс проверки электронной почты. Как только пользователь завершит процесс проверки, он обновит идентификатор на новом устройстве так же, как идентификатор первого устройства, и так далее. Лучшая его часть - это все автомагия! Вы просто интегрируете компоненты и вводите их адрес электронной почты. Вы должны быть в состоянии все это и работать в течение часа.

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

Мы действительно реализовали, и он работает ОЧЕНЬ хорошо!

ПРИМЕЧАНИЕ. По состоянию на 1 июля 2013 года Urban Airship обесценивает функциональность подписки и восстановления

Ответ 4

Создание UUID, например, предложенного Эриком, безусловно, является прочным решением. Единственное (небольшое) предостережение может заключаться в том, что в случае полного восстановления iDevice брелок будет также протер. Приложение будет генерировать новый UUID в этом сценарии, и iDevice больше не может быть связан с существующим пользователем.

Еще один подход к уникальной идентификации iDevice - создать уникальный идентификатор на основе MAC-адреса сетевого интерфейса и объединить его с идентификатором пакета приложений. Эти методы дают уникальный идентификатор, специфичный для приложения и долговечный. Он не изменится, когда iDevice будет очищено, восстановлено или когда приложение будет удалено и переустановлено. Из-за этого нет необходимости хранить этот идентификатор в цепочке ключей.

К счастью, уже есть люди, которые создали небольшую библиотеку для достижения этой цели. Код можно найти на GitHub:

https://github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5

Ответ 5

Альтернативой предложению Эрика является сторонняя библиотека, называемая OpenUDID. Вы можете создать уникальный идентификатор для каждого устройства, и он мертв просто:

#include "OpenUDID.h"
NSString* openUDID = [OpenUDID value];

Ответ 6

Как насчет использования игрового центра и iCloud для идентификации пользователя?

Менее вероятно, что пользователь не играет в игру и не синхронизирует свои данные.

Ответ 7

Вы можете использовать сторонние решения, такие как SECUREUDID также проверить это

Ответ 8

Это не абсолютно уверенное решение (и работает только при включенном iCloud), но его очень легко реализовать: Создайте уникальный идентификатор один раз (например, UUID) и сохраните его в хранилище ключей iCloud.

Единственная проблема заключается в том, что продвинутые пользователи знают, как удалить контент из iCloud.

Чтобы пользователь не просто редактировал уникальный идентификатор, хранящийся в iCloud, для другого идентификатора, вы можете добавить какой-то секрет.

Ответ 9

Сегодня наш APP был отклонен из-за идентификации пользователя Game Center. Это в Руководстве по магазинам в магазине: https://developer.apple.com/appstore/resources/approval/guidelines.html.

Вы не можете использовать uniqe Game Center ID в формате G:

Единственный способ для нас - использовать интеграцию iOS6 Facebook.

UPDATE: наша новая версия с автоматическим входом в систему FB прошла процесс рассмотрения и доступна в App Store (Slovni Duel). Использует также подписку inApp, связанную с профилем FB.

Ответ 10

Swift3/4+

Использование идентификатора записи iCloud (CKRecordID). Этот идентификатор будет уникальным для учетной записи iTunes.

let container = CKContainer.default()
container.fetchUserRecordID() {
    recordID, error in

    if let err = error {
        print(err.localizedDescription)
    }
    else if recID = recordID {
        print("fetched ID \(recID.recordName ?? "NA")")
    }
}

Для автоматически создаваемых записей строка имени идентификатора основана на UUID и поэтому гарантированно будет уникальной.