私は現在、最初のネイティブiPhoneアプリを開発しています(ただし、Web開発者として長年の経験があります)。ログインを処理するための最良の方法を理解するのに苦労しており、それを実行するための最良の方法に関するアドバイスを探しています。ログイン中に問題が発生する可能性のあるすべてのことについて考えれば考えるほど、私の脳は頭から飛び出したいと思うようになります。私はこれに本当に不満を感じており、経験豊富なiPhone開発者からのアドバイスを実際に使うことができます。よろしくお願いします。
私の目標は、アプリの最初のバージョンでFacebook Connectをサポートし、その後、他のSSOサービス(Twitter、Googleなど)と、将来のバージョンで自分のユーザーアカウントシステムをサポートすることです。現在の計画では、サーバー上に次のようなMySQLテーブルを配置する予定です。
users (id, nickname, facebook_id, ...)
ユーザーがFacebook経由でアプリに初めてログインすると、このテーブルにユーザー用のエントリが作成されます。これは必要ないと思われるかもしれませんが、後で他のサービスに拡張できるようになります。たとえば、私はこれを行うことができます:
users (id, nickname, facebook_id, twitter_id, google_id, username, ...)
このテーブルには、facebook_id、twitter_id、google_id、およびusernameのnull許容フィールドがあります。ユーザーがFacebookでログインすると、facebook_idが表示されます。Twitterユーザーにはtwitter_id、Googleユーザーにはgoogle_id、そして私自身のユーザーにはユーザー名があります。使用しているログインシステムに関係なく、すべて自分のIDで一意に識別されます。
したがって、ユーザーアカウントのバックエンド実装にはかなり満足しています。アプリがユーザーの作成/取得、ログインの確認などを行うために呼び出すことができるWebサービスをセットアップできます。問題ありません。
私が抱えている問題は、iPhoneUIコンポーネントを使用して適切なログインフローを実装することです。私の特定のアプリは、メインナビゲーションとして機能するUITabBarControllerを使用しています。タブの1つには「マイアカウント」というラベルが付いており、現在ログインしているユーザーに関する情報が含まれています。ユーザーが[マイアカウント]タブをクリックすると、サブメニューとして機能するテーブルビューが表示されます。「マイプロファイル」、「設定」などのオプションがあります。これらのメニュー項目のいずれかをクリックしてもログインしていない場合は、presentViewController関数を使用してログイン画面をポップアップします。彼らは「Facebookでログイン」をクリックし、典型的なFacebook認証プロセスを通過します。彼らがそのプロセスを完了したら、私はdismissViewControllerを使用しますログインページを削除して、アクセスしようとしたページを表示します。ログインをキャンセルした場合、またはログインに失敗した場合は、UINavigationControllerでpopViewControllerAnimatedを使用して、[マイアカウント]サブメニューに送り返します。これを想像するのに苦労している人のために、Amazonアプリをチェックしてください。これはほとんど同じです(ログインしていないときに[その他]タブをクリックして、その下にあるメニュー項目の1つをクリックしてみてください)。
それはすべてかなりうまく機能し、私はそれに満足しています。しかし、ここで私は混乱します:
[マイアカウント]タブ内のUINavigationControllerの数レベル深く、ログインセッションが期限切れになった場合、どうすればよいですか?
Facebookのログインを例にとってみましょう。Facebookは、セッショントークンを使用して、ユーザーのログインを維持します。トークンは、一定の時間が経過すると期限切れになります。ユーザーが[マイアカウント]に移動し、[マイプロファイル]をクリックしてから[編集]をクリックすると、プロファイル情報を編集できる画面が表示されたとします。したがって、このページを表示するには、明らかに認証が必要です。実際、それらはページの2〜3レベルの深さであり、表示するには認証が必要です。今、彼らが電話か何かによって中断されて、彼らが何をしていたかをすべて忘れたとしましょう。次にアプリにアクセスするのは、1週間後のログインセッションの有効期限が切れたときです。私はこれをいくつかの方法で処理できます。それらのどれも私には素晴らしいようには見えません。
解決策#1
Facebook SDKは、期限切れのセッションを通知するAppDelegateクラスのメソッドを自動的に呼び出します。AppDelegateレベルでセッションの有効期限が通知されるため、ユーザーが現在表示しているページと、それを使用するために認証が必要かどうかがわかりません。これを回避するために、「ProtectedViewController」クラスを拡張するためにログインが必要なすべてのViewController、またはそのページを表示するためにユーザーがログインする必要があることを示す何かを持つことができます。次に、AppDelegateにセッションの有効期限が通知されると、現在のViewControllerが何であるかを把握し、「ProtectedViewController」が拡張されているかどうかを確認しようとします。含まれている場合は、ログイン画面を表示します。ユーザーが正常にログインすると、すべてが通常どおり続行されます。そうでない場合は、次に、ユーザーをアプリの最初の画面に戻し、最初からやり直す必要があります。ユーザーがすでに入力したものをすべて失うため、これは悪いことですが、このソリューションでそれを回避する方法はわかりません。
解決策#2
AppDelegateレベルでセッションの有効期限イベントを無視し、代わりにこれを行います。ユーザーがログインする必要があるアクションを実行する前に(たとえば、ユーザーが[プロファイルの編集]ページで[保存]をクリックした場合)、まだログインしているかどうかを確認します。ログインしていません。そうでない場合は、ログイン画面を表示します。ユーザーがログインに失敗した場合は、スタート画面に送り返します。この解決策は、ユーザーがアプリの保護された領域内で行うほとんどすべてのこと(ページを表示するとき、ボタンをクリックするとき)をチェックする必要があるため、コードを書くのが面倒です。
また、ユーザーが再認証に失敗した場合に、ユーザーをアプリのスタート画面に戻すことは避けたいと思います。代わりに、この場合、ユーザーをUINavigationControllerの[マイアカウント]メニューにバックアップすることをお勧めします。これは、ログインを必要としない最も近いページです。もちろん、それをハードコーディングすることはできますが、もう少し自然に機能し、他のアプリで再利用できるソリューション/パターンを探しています。
いくつかのガイダンスを本当にいただければ幸いです。確かに、私はこの問題を解決する必要がある世界で最初の人ではありません。残念ながら、Googleはあまり役に立ちませんでした。
ありがとう。
編集:別のアイデアは、UIViewController(「ProtectedViewController」など)をサブクラス化し、「viewWillAppear」メソッドを実装することです。このメソッド内で、ユーザーがログインしているかどうかを確認できます。ログインしていない場合は、ログインページを上にスライドします。ただし、ログインに失敗した場合の対処方法はまだわかりません。ただし、このソリューションには問題があります。ユーザーがアプリの使用中にセッションが期限切れになった場合、次に新しいビューをクリックするまで、ユーザーを再認証しません。彼らがすでに「編集」ページを見て「保存」ボタンをクリックしている場合、彼らは再認証されません。しかし、おそらくこれは解決策に一歩近づいています。