40

我想在服务器上为应用程序的新用户创建一个用户帐户,但我也不想要求用户输入任何内容。理想情况下,我希望这是自动的,就像 Game Center 一样。

但我想知道这是否可能。有什么可以用来唯一标识用户的吗?我很难找到用户的 Apple ID。此外,设备 ID 唯一标识设备,而不是用户,因此如果用户拥有更多设备,它将无用......

还有什么我可以使用的吗?

关于隐私——我不想在用户背后找出任何东西。我要求用户访问他们的信息绝对没有问题(如果有一个 API 可以授予我这些信息,那么如果 API 自己提出这个问题,那就太好了)。正如史蒂夫乔布斯本人所说,这就是隐私的全部意义——强制应用在对他们的私人数据做任何事情之前征求用户的许可。

4

10 回答 10

31

正确的解决方案是使用iCloud Key-Value Store,您可以在其中存储唯一的用户 ID,而无需任何类型的身份验证或用户信息,例如电子邮件地址。

最终结果是一个随机的 UUID(实际上并没有识别用户),每个用户都不同,但会在注册到同一个 iCloud 帐户的多个设备上持续存在。

我们在 iCloud KV Store 中定义了一个字段,我们称之为 userID。当应用程序启动时,我们首先检查用户 ID。如果它在那里,那么我们都设置了我们用户的唯一 ID。如果不是,那么这是我们第一次为这个用户运行。我们生成一个随机的 UUID 并将其存储在 userID 下的 KV Store 中。这里的所有都是它的。

我们的经验表明,此 UUID 对于每个 iTunes 帐户都是唯一的。如果您的最终用户正在使用家庭共享,则这些帐户将被分配不同的 UUID(这可能是可取的,也可能不是可取的,但您无能为力)。在同一 iTunes 帐户下启动的任意数量的设备都将看到相同的 UUID。

这种方法是完全合法的,应该得到 Apple 的批准,没有任何问题。

显然你必须在 Xcode 的 Capabilities 下启用 iCloud Key-Value store,只需打开 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];

享受。

于 2015-12-27T19:39:05.363 回答
21

用这个生成一个 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];

请注意,所有这些都可以在没有用户输入的情况下完成。

更新:

MCSMKeychainItem为 UUID 生成和存储提供了一个很好的解决方案[MCSMApplicationUUIDKeychainItem applicationUUID]。图书馆也有[MCSMGenericKeychainItem genericKeychainItemWithService:service username:username password:password]。这些功能一起处理上述所有内容。使用CocoaPods也很容易安装。

于 2012-07-22T02:08:19.383 回答
3

拉杜

很好的问题。我们通过将 Urban Airship (urbanairship.com) 集成到我们的应用程序中解决了您描述的问题。Urban Airship 提供了一系列功能来支持应用内购买、收据验证、订阅恢复、内容交付和 Apple 推送通知。

Urban Airship 的一大优点是它能够通过电子邮件地址识别“用户”,而不是设备,而是“用户”。它并不是真正的广告“功能”......更多的是其预期功能的副产品。

以下是我们的发现以及我们如何利用 Urban Airship 来解决您遇到的问题。

当用户安装集成了 Urban Airship 的应用程序时,UA 会以某种方式生成一个类似 UDID 的编号,该编号目前仅用于识别设备。

但是,如果您利用 Urban Airship 的订阅恢复组件,您可以让用户输入电子邮件地址。一旦用户在第一台设备上输入他们的电子邮件地址……生成的 ID 就成为他们识别用户的主要方法,并与该电子邮件地址相关联。当他们在后续设备上输入电子邮件地址时,Urban Airship 将触发电子邮件验证过程。用户完成验证过程后,它会将新设备上的 ID 更新为与第一台设备的 ID 相同,依此类推。它最好的部分是......这都是自动魔法!您只需集成组件并让用户输入他们的电子邮件地址。您应该能够在一个小时内完成所有工作。

它还提供允许用户更改与其所有设备关联的电子邮件地址的功能。

我们实际上已经实施并且效果很好!

注意:截至 2013 年 7 月 1 日,Urban Airship 将弃用订阅和恢复功能

于 2012-07-25T20:26:23.147 回答
1

像 Erik 建议的那样生成 UUID 绝对是一个可靠的解决方案。唯一的(小)警告可能是,在完全 iDevice 恢复的情况下,钥匙串也将被擦除。在这种情况下,应用程序将生成一个新的 UUID,并且 iDevice 不能再与现有用户相关联。

另一种唯一标识 iDevice 的方法是根据网络接口的 MAC 地址生成唯一 id,并将其与 app bundle id 结合。这种方法会产生一个特定于应用程序且持久的唯一 id。当 iDevice 被擦除、恢复或应用程序被删除并重新安装时,它不会改变。因此,无需将此 id 存储在钥匙串中。

幸运的是,已经有人创建了一个小库来实现这一点。代码可以在 GitHub 上找到:

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

于 2012-07-27T12:02:26.283 回答
1

斯威夫特3/4+

使用 iCloud 记录 ID (CKRecordID)。此 ID 对于 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")")
    }
}

对于自动创建的记录,ID 名称字符串基于 UUID,因此保证是唯一的。

请注意,如果设备没有 iCloud 帐户,或者有访问受限的 iCloud 帐户,这将返回 CKError.Code.notAuthenticated错误

于 2019-04-09T13:51:36.887 回答
0

Erik 建议的替代方案是名为OpenUDID的第三方库。您可以为每个设备生成一个唯一标识符,这非常简单:

#include "OpenUDID.h"
NSString* openUDID = [OpenUDID value];
于 2012-07-30T20:30:40.503 回答
0

It is not an absolute sure solution (and only works when iCloud enabled), but it is very easy to implement: Generate a unique ID once (like UUID) and store it in iCloud key-value-storage.

The only problem is that advanced users know how to delete content from the iCloud.

To prevent the user just editing the unique ID stored in iCloud to someone else ID you can add some kind of secret to.

于 2012-08-01T10:37:06.177 回答
0

You can use third party solutions like SECUREUDID also check out this

于 2012-08-01T10:32:09.790 回答
0

今天我们的APP被拒绝了,因为Game Center用户识别。它在 App Store 指南中:https ://developer.apple.com/appstore/resources/approval/guidelines.html 。

您不能使用 G: 格式的唯一游戏中心 ID。

我们现在唯一的方法是使用 iOS6 Facebook 集成。

更新:我们带有自动 FB 登录功能的新版本通过了审核流程,可在 App Store (Slovni Duel) 上找到。还使用链接到 FB 个人资料的 inApp 订阅。

于 2013-02-25T21:37:20.880 回答
0

游戏中心和iCloud一起使用如何识别用户?

用户不太可能不玩游戏并且不同步他们的数据。

于 2012-08-01T03:36:01.870 回答