Как обрабатывать аутентификацию в приложениях для iPhone

В настоящее время я разрабатываю свое первое родное приложение для iPhone (хотя у меня многолетний опыт веб-разработчика). У меня возникли некоторые трудности с пониманием того, как лучше всего обрабатывать вход в систему, и я ищу несколько советов о том, как лучше всего это сделать. Чем больше я думаю обо всех вещах, которые могут пойти не так во время входа в систему, тем больше мой мозг хочет выпрыгнуть из головы. Меня это очень расстраивает, и мне действительно пригодились бы некоторые советы от более опытных разработчиков iPhone. Заранее спасибо за вашу помощь.

Моя цель — поддерживать Facebook Connect в первой версии приложения, а затем поддерживать другие службы SSO (Twitter, Google и т. д.), а также мою собственную систему учетных записей пользователей в будущих версиях.Текущий план состоит в том, чтобы иметь на сервере таблицу MySQL, которая выглядит примерно так:

users (id, nickname, facebook_id, ...)

Когда пользователь впервые входит в приложение через Facebook, для него будет создана запись в этой таблице. Вы можете подумать, что в этом нет необходимости, но это позволит мне позже использовать другие сервисы. Например, я мог бы сделать так:

users (id, nickname, facebook_id, twitter_id, google_id, username, ...)

В этой таблице будут поля, допускающие значение NULL, для facebook_id, twitter_id, google_id и имени пользователя. Если пользователь входит в систему через facebook, у него будет facebook_id. Пользователи Twitter будут иметь twitter_id, пользователи Google — google_id, а мои собственные пользователи — имя пользователя. Все они будут однозначно идентифицированы моим собственным идентификатором, независимо от того, какую систему входа они используют.

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

Проблема, с которой я столкнулся, заключается в реализации правильного процесса входа в систему с помощью компонентов пользовательского интерфейса iPhone. Мое конкретное приложение использует UITabBarController, который служит основной навигацией. Одна из вкладок называется «Моя учетная запись» и содержит информацию о вошедшем в систему пользователе. Если пользователь нажимает на вкладку «Моя учетная запись», ему предоставляется табличное представление, которое служит подменю. В нем есть такие опции, как «Мой профиль», «Настройки» и некоторые другие вещи. Если они нажимают на любой из этих пунктов меню и не вошли в систему, я использую функцию presentViewController , чтобы открыть экран входа в систему. Они нажимают «войти через facebook» и проходят стандартный процесс авторизации в Facebook.Когда они завершат этот процесс, я использую rejectViewController, чтобы удалить страницу входа и отобразить страницу, к которой они пытались получить доступ. Если они отменяют вход в систему или если вход завершается неудачно, я использую popViewControllerAnimatedв UINavigationController, чтобы отправить их обратно в подменю «Моя учетная запись». Для тех из вас, кому трудно представить себе это, ознакомьтесь с приложением Amazon. Это почти то же самое (просто щелкните вкладку «Дополнительно», когда вы не вошли в систему, и попробуйте щелкнуть один из пунктов меню под ней).

Все это работает довольно хорошо, и я доволен этим. Но вот где я запутался:

Что, черт возьми, мне делать, если они находятся на несколько уровней глубже в UINavigationController на вкладке «Моя учетная запись», а их сеанс входа в систему истекает?

Возьмем, к примеру, вход через Facebook. Facebook использует токены сеанса, чтобы пользователи оставались в системе. Срок действия токенов истекает через определенное время. Допустим, пользователь перешел в «Моя учетная запись», затем щелкнул «Мой профиль», а затем щелкнул «Изменить», и ему показан экран, на котором он может редактировать информацию своего профиля. Таким образом, они, очевидно, должны быть аутентифицированы для просмотра этой страницы. На самом деле, они находятся на 2-3 уровня глубже страниц, для просмотра которых им необходимо пройти аутентификацию. Теперь предположим, что их прервал телефонный звонок или что-то в этом роде, и они забыли о том, что делали. В следующий раз они получат доступ к приложению через неделю, когда истечет срок их сеанса входа в систему. Я могу справиться с этим несколькими способами. Ни один из них не кажется мне великим.

Решение №1

Facebook SDK автоматически вызовет метод класса AppDelegate, который уведомит меня об истечении срока действия сеанса. Поскольку я уведомлен об истечении срока действия сеанса на уровне AppDelegate, я понятия не имею, какую страницу в данный момент просматривает пользователь и нужно ли им проходить аутентификацию, чтобы использовать ее. Чтобы обойти это,У меня могут быть все ViewController, которым требуется вход в систему для расширения класса «ProtectedViewController» или что-то, что указывает, что пользователь должен войти в систему, чтобы увидеть эту страницу. Затем, когда AppDelegate уведомляется об истечении срока действия сеанса, он попытается выяснить, что такое текущий ViewController, и проверить, расширяет ли он «ProtectedViewController». Если это так, представьте экран входа в систему. Если пользователь успешно входит в систему, все происходит как обычно. Если нет, то верните пользователя на первый экран приложения, где ему придется начинать все сначала. Это плохо, потому что пользователь потеряет все, что он уже набрал, но я не вижу способа избежать этого с помощью этого решения.

Решение № 2

Игнорировать событие окончания сеанса на уровне AppDelegate и вместо этого сделать следующее: перед выполнением любого действия, требующего входа пользователя в систему (например, когда пользователь нажимает «Сохранить» в своем «Редактировать профиль»). "), проверьте, вошли ли они в систему. Если это не так, представьте экран входа в систему. Если пользователю не удается войти в систему, отправьте его обратно на начальный экран. Это решение — головная боль для кода, потому что мне приходится проверять практически все, что пользователь делает в защищенной области приложения — когда он просматривает страницу, когда нажимает кнопку — почти все.

Я бы также предпочел не отправлять пользователя обратно на начальный экран приложения, если ему не удалось пройти повторную аутентификацию. Вместо этого, в этом случае, я бы предпочел отправить пользователю резервную копию UINavigationController в меню «Моя учетная запись», которая является ближайшей страницей, не требующей входа в систему.Конечно, я мог бы жестко закодировать это, но я ищу решение/шаблон, который работает немного более естественно и который я могу повторно использовать в других приложениях.

Буду очень признателен за совет. Наверняка я не первый человек в мире, которому понадобилось решить эту проблему. К сожалению, Google не сильно помог.

Спасибо.

РЕДАКТИРОВАТЬ: Другая идея состоит в том, чтобы создать подкласс UIViewController (например, «ProtectedViewController») и реализовать метод «viewWillAppear». Внутри этого метода я могу проверить, вошел ли пользователь в систему. Если нет, я открываю страницу входа. Однако я до сих пор не знаю, как поступить в случае, когда им не удается войти в систему. Однако у этого решения есть проблема: если сеанс пользователя истекает, когда он использует приложение, я не буду повторно аутентифицировать его до тех пор, пока он в следующий раз не нажмет на новое представление. Если они уже просматривают, скажем, страницу «редактировать» и нажимают кнопку «Сохранить», то они не будут повторно аутентифицированы. Но, возможно, это шаг ближе к решению.

6
задан Kevin Craft 29 May 2012 в 15:29
поделиться