web-dev-qa-db-ja.com

iOSユーザーを一意に識別する

アプリの新規ユーザー用にサーバー上にユーザーアカウントを作成したいのですが、ユーザーに何も入力するように求めないようにします。理想的には、Game Centerのように、これを自動化したいです。

しかし、それが可能かどうか疑問に思っています。ユーザーを一意に識別するために使用できるものはありますか?ユーザーのApple= IDを見つけることができる可能性はほとんどありません。また、デバイスIDはユーザーではなくデバイスを一意に識別するため、ユーザーがさらに多くのデバイスを持っている場合は役に立ちません...

他に使用できるものはありますか?

プライバシーについて-ユーザーの裏で何かを知りたくありません。私はユーザーに情報へのアクセスを要求することにはまったく問題がありません(この情報を許可するAPIがあれば、APIがそれ自体を要求するのは素晴らしいことです)。 Steve Jobs氏自身が言ったように、これがプライバシーのすべてです。つまり、アプリがユーザーの個人データを操作する前にユーザーに許可を求めることです。

37
rid

正しい解決策は iCloud Key-Value Store を使用することです。この場合、認証やメールアドレスなどのユーザー情報を必要とせずに一意のユーザーIDを保存できます。

最終結果はランダムなUUID(実際にはユーザーを識別するものではありません)であり、ユーザーごとに異なりますが、同じiTunesアカウントに登録された複数のデバイスに対して同じ値になります

ICloud KVストアにフィールドを定義し、userIDと呼びましょう。アプリが起動すると、最初にユーザーIDを確認します。そこにある場合は、ユーザーの一意のIDがすべて設定されています。そうでない場合は、このユーザーに対して実行するのはこれが初めてです。ランダムなUUIDを生成し、userIDでKVストアに格納します。これですべてです。

私たちの経験によると、このUUIDはiTunesアカウントごとに一意です。エンドユーザーが家族共有を使用している場合、それらのアカウントには異なるUUIDが割り当てられます(これは望ましい場合と望ましくない場合がありますが、それに対してできることは何もありません)。同じiTunesアカウントで起動するデバイスの数に関係なく、同じUUIDが表示されます。

このアプローチは完全に合法であり、Appleによって問題なく承認される必要があります。

明らかに、機能の下のXcodeでiCloud Key-Valueストアを有効にする必要があります。iCloudスイッチをオンにするだけです。

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];

楽しい。

26
ldoogy

これで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 は、[MCSMApplicationUUIDKeychainItem applicationUUID]を使用したUUIDの生成と保存に優れたソリューションを提供します。ライブラリには[MCSMGenericKeychainItem genericKeychainItemWithService:service username:username password:password]もあります。これらの機能が連携して、上記のすべてを処理します。 CocoaPods でも簡単にインストールできます。

21
Erik

ラドゥ

すばらしい質問です。アーバンエアシップ(urbanairship.com)をアプリに統合することで、お客様が説明した問題を解決しました。アーバンエアシップは、アプリ内購入、レシート検証、サブスクリプションの回復、コンテンツ配信、およびAppleプッシュ通知をサポートするための機能のグラブバッグを提供します。

アーバンエアシップの優れた点の1つは、デバイスではなく「ユーザー」を特定できることです。電子メールアドレスで「ユーザー」を特定できます。これは実際に宣伝されている「機能」ではなく、意図された機能の副産物です。

これが私たちが見つけたものであり、Urban Airshipを利用して問題を解決する方法を示しています。

ユーザーがアーバンエアシップが統合されたアプリをインストールすると、UAはなんらかの方法でUDIDのような番号を生成します。この番号は、現時点では単にデバイスを識別します。

ただし、Urban Airshipのサブスクリプション回復コンポーネントを利用する場合は、ユーザーにメールアドレスを入力させることができます。ユーザーが最初のデバイスでメールアドレスを入力すると、その生成されたIDがユーザー識別の主要な方法になり、そのメールアドレスに関連付けられます。後続のデバイスでメールアドレスを入力すると、Urban Airshipはメール検証プロセスをトリガーします。ユーザーが検証プロセスを完了すると、新しいデバイスのIDが最初のデバイスのIDと同じになるように更新されます。それの最も良い部分は...それはすべて自動魔法です!コンポーネントを統合して、ユーザーにメールアドレスを入力させるだけです。 1時間以内にすべてを稼働させることができるはずです。

また、ユーザーが自分のすべてのデバイスに関連付けられている電子メールアドレスを変更できるようにする機能も提供します。

実際に実装しましたが、非常にうまく機能します!

注:2013年7月1日の時点で、Urban Airshipはサブスクリプションとリカバリ機能を非推奨にしています

4
radesix

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

1
Bas Peters

Swift3/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に基づいているため、一意であることが保証されています。

0
Abhijith

Game CenterとiCloudを一緒に使用してユーザーを特定するのはどうですか?

ユーザーがゲームをプレイせず、データを同期しない可能性は低くなります。

0
Mickey

[〜#〜] secureudid [〜#〜] のようなサードパーティのソリューションを使用することもできます this

0
msk

今日、Game CenterのユーザーIDのため、APPは拒否されました。それはApp Storeのガイドラインにあります: https://developer.Apple.com/appstore/resources/approval/guidelines.html

Uniqe Game Center IDをG:形式で使用することはできません。

私たちにとって今の唯一の方法は、iOS6 Facebook統合を使用することです。

更新:自動FBログオンのレビュープロセスに合格した新バージョンはApp Store(Slovni Duel)で入手できます。 FBプロファイルにリンクされたinAppサブスクリプションも使用します。

0
Lubomir

これは完全に確実な解決策ではありません(iCloudが有効な場合にのみ機能します)が、実装が非常に簡単です。一意のIDを1回(UUIDのように)生成し、それをiCloudキー値ストレージに保存します。

唯一の問題は、上級ユーザーがiCloudからコンテンツを削除する方法を知っていることです。

ユーザーがiCloudに保存されている一意のIDを他の誰かのIDに編集するのを防ぐには、何らかのシークレットを追加できます。

0
miho

Erikの提案に代わるものは、 OpenUDID と呼ばれるサードパーティのライブラリです。デバイスごとに一意の識別子を生成できます。これは非常に簡単です。

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