如何在iPhone应用程序中处理身份验证

Kev*_*aft 6 iphone facebook ios

我目前正在开发我的第一个原生iPhone应用程序(虽然我有多年的Web开发经验).我在理解处理登录的最佳方式时遇到了一些困难,我正在寻找一些关于最佳方法的建议.我越想到登录过程中可能出现的所有问题,我的脑子就越想跳出脑袋.我对此非常感到沮丧,并且可以真正使用一些更有经验的iPhone开发人员的建议.在此先感谢您的帮助.

我的目标是在应用程序的第一个版本中支持Facebook Connect,然后在将来的版本中支持其他SSO服务(Twitter,Google等)以及我自己的用户帐户系统.目前的计划是在服务器上有一个MySQL表,如下所示:

users (id, nickname, facebook_id, ...)
Run Code Online (Sandbox Code Playgroud)

当用户第一次通过Facebook登录应用程序时,将在此表中为他们创建一个条目.您可能认为这不是必需的,但它将允许我稍后扩展到其他服务.例如,我可以这样做:

users (id, nickname, facebook_id, twitter_id, google_id, username, ...)
Run Code Online (Sandbox Code Playgroud)

此表将具有可用于facebook_id,twitter_id,google_id和用户名的可空字段.如果用户使用facebook登录,他们将拥有facebook_id.Twitter用户将拥有twitter_id,Google用户将拥有google_id,而我自己的用户将拥有用户名.无论他们使用什么登录系统,它们都将由我自己的id唯一标识.

所以我对用户帐户的后端实现很满意.我可以设置一个Web服务,应用程序可以调用该服务来创建/检索用户,验证登录等.没问题.

我遇到的问题是使用iPhone UI组件实现正确的登录流程.我的特定应用程序使用UITabBarController作为主导航.其中一个选项卡标有"我的帐户",其中包含有关当前登录用户的信息.如果用户单击"我的帐户"选项卡,则会显示一个用作子菜单的表视图.它有诸如"我的个人资料","设置"等一些选项.如果他们点击任何这些菜单项并且他们没有登录,那么我使用presentViewController功能弹出登录屏幕.他们点击"使用Facebook登录"并完成典型的Facebook授权流程.当他们完成该过程时,我使用dismissViewController删除登录页面并显示他们试图访问的页面.如果他们取消登录或登录失败,那么我在UINavigationController上使用popViewControllerAnimated将它们发送回"我的帐户"子菜单.对于那些难以想象的人,请查看亚马逊应用程序.它几乎完全相同(只需在您未登录时单击"更多"选项卡并尝试单击其下的一个菜单项).

这一切都很好,我很高兴.但是这里我感到困惑:

如果他们在"我的帐户"标签中的UINavigationController深入几层并且他们的登录会话到期,我该怎么办?

我们以Facebook登录为例.Facebook使用会话令牌来保持用户登录.令牌在一段时间后过期.假设用户导航到"我的帐户",然后单击"我的个人资料",然后点击"编辑",并显示一个屏幕,用户可以在其中编辑他们的个人资料信息.所以他们显然需要进行身份验证才能查看此页面.实际上,它们需要经过身份验证才能看到的页面深度为2-3级.现在让我们说他们被电话或其他东西打断了,忘记了他们在做什么.他们下次访问应用程序的时间是一周后他们的登录会话已过期.我可以通过几种方式解决这个问题.他们似乎对我来说都不是很好.

解决方案#1

Facebook SDK将自动调用AppDelegate类上的方法,该方法通知我过期的会话.由于我在AppDelegate级别收到会话到期通知,因此我不知道用户当前正在查看哪个页面以及是否需要对其进行身份验证才能使用它.为了解决这个问题,我可以让所有需要登录的ViewControllers扩展"ProtectedViewController"类或者指示用户应该登录以查看该页面的内容.然后,当AppDelegate被通知会话到期时,它将尝试找出当前的ViewController是什么,并检查它是否扩展了"ProtectedViewController".如果是,则显示登录屏幕.如果用户成功登录,则一切都正常进行.如果没有,则将用户返回到他们必须从头开始的应用程序的第一个屏幕.这很糟糕,因为用户将丢失他们已经输入的任何内容,但我认为没有办法通过此解决方案来避免它.

解决方案#2

忽略AppDelegate级别的会话过期事件,而是执行此操作:在执行任何需要用户登录的操作之前(例如,当用户在"编辑个人资料"页面上单击"保存"时),检查他们是否仍然登录.如果不是,则显示登录屏幕.如果用户登录失败,则将其发送回开始屏幕.这个解决方案很难解决问题,因为我必须检查用户在应用程序的受保护区域内执行的所有操作 - 当他们查看页面时,单击按钮时 - 几乎所有内容.

如果用户无法重新进行身份验证,我还是希望避免将用户一直发送回应用的开始屏幕.相反,在这种情况下,我更愿意将用户备份UINavigationController发送到"我的帐户"菜单 - 这是最近的页面,不需要登录.当然,我可以对其进行硬编码,但我正在寻找一种可以更自然地工作的解决方案/模式,并且我可以在其他应用程序中重复使用.

我真的很感激一些指导.当然,我不是世界上第一个需要解决这个问题的人.不幸的是,谷歌没有太多帮助.

谢谢.

编辑:另一个想法是子类UIViewController(例如"ProtectedViewController")并实现"viewWillAppear"方法.在这个方法中,我可以检查用户是否已登录.如果没有,那么我将滑动登录页面.但是,当他们登录失败时,我仍然不知道如何处理这个案子.但是,此解决方案存在一个问题:如果用户的会话在使用应用程序时到期,那么在下次单击新视图之前,我不会重新对其进行身份验证.如果他们已经在查看"编辑"页面并单击"保存"按钮,则不会重新进行身份验证.但也许这是更接近解决方案的一步.

Ani*_*nil 0

这是我如何在最近的项目中使用单例来管理它的。

创建一个单例类,例如 LoginManager,它有一个名为的方法,

-(UserInfo*) getValidatedUser: (UIView*) senderView
Run Code Online (Sandbox Code Playgroud)

在此方法中检查令牌是否仍然有效。

如果它无效,只需创建一个新视图,强制用户使用 FB 凭据登录,并将其覆盖在“senderView”之上,以便强制用户登录,如下所示:

[senderView addSubview:loginView]; 
Run Code Online (Sandbox Code Playgroud)

一旦令牌有效,您将返回用户信息。

有了这个基本逻辑,您现在可以在需要有效凭据来执行某些操作时从视图控制器类调用此 getValidatedUser 方法:

UserInfo* myUser = [loginManagerObj  getValidatedUser:self.view]
Run Code Online (Sandbox Code Playgroud)

该方法在内部决定是否应显示登录页面。希望这可以帮助。