我正在开发一个主要通过应用程序访问的网站,我想使用 OAuth2 进行用户注册和身份验证。由于它是一个 Android 应用程序,我将开始使用 Google 的 OAuth2 东西,因为它在 Android 上提供了一个不错的 UI。
谷歌表示“您可以选择使用 Google 的身份验证系统来外包应用程序的用户身份验证。这可以消除创建、维护和保护用户名和密码存储的需要。” https://developers.google.com/accounts/docs/OAuth2Login这就是我想做的。However当我浏览他们所有的例子和诸如此类的东西时,我只能找到关于拥有一个网站的东西or应用程序根据 Google 的服务对用户进行身份验证。
事实上,当我用 Google 的 OAuth2 注册我的应用程序(“客户端”)时,可以选择网站客户端和“已安装”客户端(即移动应用程序),但不能同时选择两者。我可以创建两个单独的客户端,但我阅读了 OAuth2 草案,我认为会有一个问题,我现在将对此进行解释。
这是我设想的它的工作方式:
- 用户要求 MyApp 访问他的私人数据。
- 应用程序使用Android
AccountManager
类来请求 Google API 的访问令牌。
- Android 对用户说“应用程序‘MyApp’想要访问您在 Google 上的基本信息。可以吗?”
- 用户说是的。
-
AccountManager
使用手机上存储的凭据连接到 Google 的 OAuth2 服务器,并请求访问令牌。
- 返回访问令牌(位于绿线后面)。
-
AccountManager
将访问令牌返回给 MyApp。
- MyApp 向 MySite 发送请求以获取用户的私有数据,包括访问令牌。
- MySite 需要使用访问令牌验证用户。它验证令牌如此处所述 https://developers.google.com/accounts/docs/OAuth2Login#validatingtoken,与 Google - “Google,此令牌有效吗?”。
- 现在,我什么want发生的情况是 Google 说“是的,无论是谁给你的,确实是那个用户。”,但我认为实际会发生的情况(基于 OAuth2 草案和 Google 的文档)是它会说“不可能!那个令牌是仅对 MyApp 有效,而您就是 MySite。GTFO!”。
那么我应该怎么做呢?并且请不要说“使用 OpenID”或“不要使用 OAuth2”或其他类似的无用答案。哦,我真的很想继续使用这个好东西AccountManager
UI 而不是蹩脚的弹出窗口WebView
s
Edit
Nikolay 的临时答案(我会报告它是否有效!)是它实际上应该有效,并且 Google 的服务器不会关心访问令牌来自哪里。对我来说似乎有点不安全,但我会看看它是否有效!
Update
我用 Facebook 而不是 Google 实现了这个模式,它完全有效。 OAuth2 服务器不关心访问令牌来自哪里。至少 Facebook 没有,所以我想 Google 也没有。
鉴于此,存储访问令牌是一个非常非常糟糕的主意!但我们也不希望必须访问 Facebook/Google 的服务器来检查身份验证every请求,因为它会减慢一切。也许最好的办法是为您的网站添加一个额外的身份验证 cookie,在验证访问令牌时分发该 cookie,但更简单的方法是将访问令牌视为密码并存储它的哈希值。您也不需要加盐,因为访问令牌真的很长。所以上面的步骤就变成了这样:
9. MySite 需要使用访问令牌验证用户。首先,它检查其散列有效访问令牌的缓存。如果在那里找到令牌的哈希值,则表明用户已通过身份验证。否则它会与 Google 核实如此处所述 https://developers.google.com/accounts/docs/OAuth2Login#validatingtoken,与 Google - “Google,此令牌有效吗?”。
10. 如果 Google 说访问令牌无效,我们会通知用户 GTFO。否则谷歌会说“是的,这是一个有效的用户”,然后我们检查我们的注册用户数据库。如果找不到该 Google 用户名(如果使用 Facebook,则为 Facebook ID),我们可以创建一个新用户。然后我们缓存访问令牌的哈希值。