在 Android 应用程序中存储用户名和密码
Posted
技术标签:
【中文标题】在 Android 应用程序中存储用户名和密码【英文标题】:Storing username and password in Android app 【发布时间】:2016-03-31 13:24:21 【问题描述】:我需要在我的 android 应用中存储用户凭据。应用程序将 HTTP 请求发送到服务器,并且凭据用于向该服务器进行身份验证。
我知道已经有很多关于这个主题的文章和讨论。但是,考虑到以下具体要求,我想寻求帮助:
应该要求用户只输入一次用户名和密码。之后,应用程序必须能够永远通过服务器进行身份验证。 如果服务器收到包含用户名和密码的身份验证请求,它会生成一个随机令牌并将其发送回客户端。 客户端必须将令牌添加到其他请求(作为 HTTP 标头)。 令牌的有效期总是在生成后一小时到期。客户端必须发送另一个带有用户名和密码的身份验证请求才能获取新令牌。请注意,服务器提供了不遵循任何标准的自定义身份验证机制。
我会说这些是非常严格的要求,并且它们已经影响了一些安全问题。但是,我们假设这些条件无法更改,Android 应用必须满足这些条件。
这是我要做的:
由于用户应在每次应用安装时只提供一次凭据,并且服务器端的令牌具有有限的有效性,并且客户端必须一次又一次地使用凭据重新进行身份验证,因此 Android 应用无法避免存储密码。 我会将凭据存储到 DB 中(通过从android.database.sqlite
包中继承 SQLiteOpenHelper
)。
我将在存储凭据之前对其进行加密,但用于加密/解密的密钥将只是在应用程序中硬编码的常量。
另外,我将在清单文件中将android:allowBackup
设置为false
并对应用程序进行混淆处理。
我知道对设备具有物理访问权限的攻击者可以获得凭据。我也知道,一些建议的步骤对于此类攻击者来说只是小障碍。
但是,如果有问题开头提到的要求,我还能做些什么来提高安全性?
谢谢。
【问题讨论】:
如果你必须走这条路,我不知道 Android 的安全性,所以我不能对此发表评论。我头顶的一件事。您将要使用的加密密钥,不要对其进行硬编码,最好为每个用户使用不同的密钥,这样如果一台设备遭到入侵并且密钥被发现,它就不能用于攻击另一台用户的设备.我相信还有很多事情可以做,我将不得不考虑更多。 @SBurris 为不同的用户使用不同的密钥很有意义。在这种情况下,我必须以确定性方式生成密钥或生成随机密钥。如果密钥是确定性的(例如从设备 ID 派生),攻击者可以反编译应用程序并找到构建密钥的算法。如果密钥是随机的,则它必须存储在某个地方。但是,如果攻击者能够找到存储的密码,他也能够找到存储的密钥。你认为哪个选项更好?还是我忽略了什么?谢谢。 【参考方案1】:如果我处于你的位置,我会使用 SQLCipher 来存储用户凭据。这是创建和使用加密(使用 AES)sqlite
数据库的简单方法。
当然,这并不能解决整个问题。您仍然需要一种安全的方式来生成/存储所述数据库的密钥。如果我要推荐任何选项,我建议要求用户在打开应用程序时输入密码/PIN,并使用所述密码/PIN 作为数据库密钥。
另一种方法是在应用安装时生成一个唯一的随机密钥,并将其存储在the Android Keystore 中。真正敬业/资金充足的攻击者仍然能够检索密钥,但只能检索该设备上的数据库。
【讨论】:
我之前已经考虑过使用SQLCipher。这是一个选择,但我最终决定不使用它。如果用户名-密码对是唯一要存储的东西,我更喜欢手动加密这个单个值,而不是依赖另一个库。 要求用户在打开应用程序时(或至少在令牌过期时)输入凭据通常是个好主意,我同意。不幸的是,在这种情况下,每次应用安装只提供一次凭据是“必须具备”的要求。 使用 Android 密钥库会很有意义。 (+1) 但是,它似乎需要 API 级别 18,我必须解决 API 级别 16(或至少 17)。 在这种情况下,您可能需要阅读this article,了解 Android 设备上不同的密钥存储策略的集合。它比我在这个空间中更深入和严谨。以上是关于在 Android 应用程序中存储用户名和密码的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 应用中使用 Firebase (BaaS) 存储电子邮件和密码时如何包含用户名?