在Android上的我的应用程序之间共享oauth令牌 - 共享用户ID,钥匙串,AccountManager或其他?
我正在努力解决特定情况下的最佳解决方案,并且无法制定出最佳选择。这是一个棘手的设置,所以对你的Android专家可能是一个有趣的挑战!这是我的情况:在Android上的我的应用程序之间共享oauth令牌 - 共享用户ID,钥匙串,AccountManager或其他?
- 我们有两个Android应用程序已经在Play商店中,并且正在使用另一个权利。
- 这两个发布的应用程序使用相同的密钥库进行签名,但目前在其清单文件中没有设置sharedUserId。
- 这两个发布的应用程序将用户的oAuth令牌存储在SharedPrefs中,SQLite数据库中的某些产品/内容数据以及外部存储中的某些音频/视频内容(使用getExternalFilesDir)。
- 这些应用程序都是独立的oAuth客户端/我们服务器的应用程序(即它们都使用不同的客户端ID和密钥)。
- 我们的服务器设置为仅允许每个oAuth应用程序(即Android应用程序)使用一个oAuth令牌。例如如果用户在一台设备上登录到应用程序A,然后登录到另一台设备上的应用程序A,则第一个设备的令牌将失效,应用程序将收到401.
- 我们成功实施了单点登录系统在iOS上启用应用程序之间的共享钥匙串。如果应用程序检测到组中的另一个应用程序具有有效的oAuth令牌,它可以将其发送给我们的服务器并将其交换为该应用程序的有效令牌。
- 在iOS版本中,我们希望确保应用程序不需要知道每个应用程序使用硬编码值的其他应用程序的存在(例如,如果我们将来会发布新应用程序, t需要更新以与它共享/接收令牌),所以我们在包含具有有效令牌的捆绑ID数组的钥匙串中创建了条目,所有应用都可以访问该令牌。当应用成功登录或交换令牌时,他们将自己的捆绑ID添加到该阵列。任何新安装的应用程序都可以从该阵列中找到包ID,并将其用作加载该应用程序的令牌详细信息的密钥,然后它将交换它自己的新令牌。
- 我们希望令牌交换是自动的,不需要用户输入。
我希望一切都有道理!请让我知道如果没有。
我现在正试图找出在Android上存储oAuth令牌(以及其他一些附加数据,例如电子邮件地址)的最佳方法,以便我们帐户拥有的其他应用可以访问它们以便交换为新鲜的令牌。
我已经研究过使用以下,但我不确定的最佳途径:
- 与sharedUserId
- 的AccountManager(https://developer.android.com/reference/android/accounts/AccountManager.html)
- 的Android钥匙扣(https://developer.android.com/reference/android/security/KeyChain.html)
- ContentProviders沿SharedPreferences
选项1的问题似乎是t o在第一次发布后设置sharedUserId将无法访问所有数据(请参阅http://java-hamster.blogspot.jp/2010/05/androids-shareduserid.html)。这对我们的用户来说不是一件好事。
选项2。(AccountManager)可能是一个不错的选择,但如果我们想单独存储令牌(每个应用程序),但希望我们为访问令牌而创建的任何其他应用程序,我不知道我们该怎么做。
选项3 ...是否有可能做我们需要的钥匙串?
如果我理解正确,选项4将需要每个应用程序拥有自己的ContentProvider?我不确定这将如何符合我们的要求。
如果有人经历过这种情况,可以分享一些见解和建议,我会很感激!
ContentProvider可能是你最好的。我将不能够提供整个代码为你做到这一点,但这通常我怎么看它的工作是:
- 每个应用程序创建一个公开自己的API令牌的内容提供商;
- 在请求登录之前,每个应用都会尝试获取并查询(按顺序直到成功)所有其他内容提供者;
- 如果应用程序X能够从应用程序Y(通过Y的内容提供商)获取并检索令牌,然后将其存储在应用程序X中并使用它;
旁注:
- 这是非常敏感的信息,所以你应该强制执行安全。您的内容提供商只应由其他使用相同密钥签名的应用访问,他们应该只拥有读取权限,您也应该创建自己的自定义权限。
- 内容提供者不需要访问sqlite数据库。它可以访问无论你使用存储令牌(我希望被存储在一个安全的方式,但我会留给你自己的判断)
相关链接:
AccountManager旨在解决您正在评论的确切问题。这里是一个很好的教程,它的工作: http://blog.udinic.com/2013/04/24/write-your-own-android-authenticator/
只要确保您注册使用相同的密钥存储所有的应用程序,因为这是一个可能使事情变得复杂(大量的)的嘛。
使用首选项会导致您遇到问题,因为您存储在主线程中的所有内容不能保证在服务中存在(如SyncAdapter)。曾经有一种以标志(MULTI_SERVICE)形式存在的技巧,但在api 23中已弃用。
ContentProvider当然是可能的(它太泛泛),但AccountManager将帮助您涵盖与刷新相关的角落案例令牌和其他有趣的东西。
感谢您的回答,@joao。我会在接下来的几天看到这个,并会告诉你它是怎么回事。 :) – Marky