【问题标题】:Sharing oauth token between my apps on Android - Shared User ID, Keychain, AccountManager or something else?在 Android 上的应用程序之间共享 oauth 令牌 - 共享用户 ID、钥匙串、AccountManager 或其他?
【发布时间】:2017-07-13 16:03:28
【问题描述】:

我正在尝试为我所处的特定情况制定最佳解决方案,但在制定最佳选择时遇到了麻烦。这是一个棘手的设置,因此对您的 Android 专家来说可能是一个有趣的挑战!这是我的情况:

  • 我们已经在 Play 商店上架了两个 Android 应用,并且正在开发另一个。
  • 这两个已发布的应用使用相同的密钥库进行签名,但目前在其清单文件中没有设置 sharedUserId。
  • 这两个发布的应用程序将用户的 oAuth 令牌存储在 SharedPrefs 中,一些产品/内容数据存储在 SQLite DB 中,一些音频/视频内容存储在外部存储中(使用 getExternalFilesDir)。
  • 这些应用程序都是我们服务器的独立 oAuth 客户端/应用程序(即它们都使用不同的客户端 ID 和密钥)。
  • 我们的服务器设置为每个 oAuth 应用程序(即 Android 应用程序)只允许一个 oAuth 令牌。例如如果用户在一台设备上登录应用 A,然后在另一台设备上登录应用 A,则第一个设备的令牌将失效,应用将收到 401。
  • 通过启用应用程序之间的共享钥匙串,我们已在 iOS 上成功实现了单点登录系统。如果应用检测到组中的另一个应用具有有效的 oAuth 令牌,它可以将其发送到我们的服务器并将其交换为该应用的有效令牌。
  • 在 iOS 版本中,我们希望确保应用不需要使用每个应用的硬编码值知道其他应用的存在(例如,如果我们将来发布新应用,其他应用不需要) t 需要更新以与其共享/接收令牌),因此我们在钥匙串中创建了一个条目,其中包含一组具有有效令牌的捆绑 ID,所有应用程序都可以访问该条目。当应用程序成功登录或交换令牌时,它们会将自己的捆绑包 ID 添加到该数组中。任何新安装的应用都可以从该数组中找到一个捆绑 ID,并将其用作加载该应用的令牌详细信息的密钥,然后它将交换自己的新令牌。
  • 我们希望令牌交换是自动的,不需要用户输入。

我希望一切都有意义!!!如果没有请告诉我。

我现在正在尝试找出在 Android 上存储 oAuth 令牌(以及一些额外的数据,例如电子邮件地址)的最佳方法,以便我们帐户拥有的其他应用可以访问它们,以便交换一个新的令牌。

我已经研究过使用以下方法,但不确定最佳路线:

  1. SharedPreferences 和 sharedUserId
  2. AccountManager (https://developer.android.com/reference/android/accounts/AccountManager.html)
  3. Android 钥匙串 (https://developer.android.com/reference/android/security/KeyChain.html)
  4. 内容提供者

选项 1. 的问题似乎是在首次发布后设置 sharedUserId 将失去对所有数据的访问权限(请参阅http://java-hamster.blogspot.jp/2010/05/androids-shareduserid.html)。这对我们的用户来说不是一件好事。

选项 2。(AccountManager)可能是一个不错的选择,但如果我们想单独存储令牌(每个应用程序),但希望我们制作的任何其他应用程序访问它们的令牌,我不确定我们如何'我要这样做。

选项3...是否可以使用钥匙串做我们需要的事情?

如果我理解正确,选项 4 是否需要每个应用程序都有自己的 ContentProvider?我不确定这将如何满足我们的要求。

如果有人遇到过这种情况并能分享一些见解和建议,我将不胜感激!

【问题讨论】:

    标签: android oauth sharedpreferences android-contentprovider accountmanager


    【解决方案1】:

    AccountManager 旨在解决您评论的确切问题。这是一个很好的教程: http://blog.udinic.com/2013/04/24/write-your-own-android-authenticator/

    请确保您使用相同的密钥库签署所有应用程序,因为这是唯一可能使事情复杂化的事情(很多)。

    使用首选项会导致您遇到问题,因为您存储在主线程中的所有内容都不能保证在服务中存在(如 SyncAdapter)。曾经有一个以标志(MULTI_SERVICE)的形式出现的技巧,但在 api 23 中已被弃用。

    ContentProvider 当然是可能的(它太通用了),但 AccountManager 将帮助您解决与刷新令牌和其他有趣内容相关的极端情况。

    【讨论】:

    • 如果一个应用已经在 PlayStore 上并且大多数用户已经登录到他们的应用,这个解决方案将如何工作?
    【解决方案2】:

    ContentProvider 可能是你最好的。我无法为您提供完整的代码来执行此操作,但这通常是我认为它的工作方式:

    1. 每个应用都会创建一个公开自己的 API 令牌的内容提供者;
    2. 在请求登录之前,每个应用都会尝试获取和查询(依次直到成功)所有其他内容提供者;
    3. 如果应用 X 能够从应用 Y 获取和检索令牌(通过 Y 的内容提供程序),则将其存储在应用 X 中并使用它;

    旁注:

    1. 这是非常敏感的信息,因此您应该加强安全性。您的内容提供者只能由使用相同密钥签名的其他应用访问,它们应该只有读取权限,您也应该创建自己的自定义权限。
    2. 内容提供者不需要访问 sqlite 数据库。它可以访问您用来存储令牌的任何内容(我希望以安全的方式存储,但我会留给您自己判断)

    有用的链接:

    1. How to create a custom content provider

    2. How to secure your content provider

    3. Example of content provider that retrieves data from shared preferences;

    【讨论】:

    • 感谢您的回答,@joao。我将在接下来的几天内对此进行调查,并告诉您进展如何。 :)
    • @Marky 你最后是怎么解决这个问题的?您是使用 ContentProvider 还是使用任何其他方法解决了它?我遇到了完全相同的问题。
    • @KashishMalhotra 恐怕我现在不记得了!我刚刚检查了我们的代码库,似乎由于某种原因我们最终没有实现它。对不起!
    猜你喜欢
    • 2018-02-15
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    相关资源
    最近更新 更多