我有一个与服务器通信的应用程序。
当用户登录到应用程序时,服务器上会创建一个身份验证令牌,并将其存储在应用程序的SharedPreferences
中,每当应用程序从Web服务请求数据时,都会验证身份验证令牌。
我的问题是,将身份验证令牌存储在SharedPreferences
中是否安全?我问,因为具有root权限的用户可以访问首选项,提取令牌并使用它。
在这方面是否有更多的安全措施?
答案 0 :(得分:36)
简而言之,是的,这是一件非常合理的事情。
除此之外,您可以做的最好的事情就是混淆。如果将令牌保留在内存中,则root用户可以查看该令牌。如果你加密它,你也必须将加密密钥存储在设备上,否则你将无法使用令牌......并且密钥可以像令牌一样容易被盗。
如果有人在设备上拥有root权限,则所有投注均已关闭。不要针对那种情况进行优化。如果您的应用程序具有超级高安全性,请不要让它在root设备上运行,或实现远程擦除功能,用户可以报告其设备被盗,并且您可以使服务器上的令牌无效。
Android 4.3引入了Android Keystore。据称这为加密密钥提供了一个安全的存储。这可用于存储用于解密使用传统方法存储的加密令牌的密钥。但是,引用的链接没有提到root设备如何影响其安全性。
更新2018年:大多数现代Android设备都通过SoC提供的可信执行环境(TEE)hardware-backed keystores。这使得黑客无法获得密钥库主密钥,否则密钥库主密钥将被解密您存储在Android密钥库中的密钥。
嗯,“不可能”是一个强有力的词。最好说“不可行”。意思是,您需要像电子显微镜这样的东西来扫描融合到提供TEE的SoC中的位。如果你是那种数据需要这种关注的人,你可能会遇到更大的问题。
答案 1 :(得分:1)
现在有一种更简单快捷的方法来加密数据,因为有一个 SharedPreferences 的实现来加密密钥和值。您可以在 Android JetPack Security 中使用 EncryptedSharedPreferences。
只需将 AndroidX Security 添加到您的 build.gradle 中:
implementation 'androidx.security:security-crypto:1.0.0-rc01'
你可以这样使用它:
String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
"secret_shared_prefs",
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
// use the shared preferences and editor as you normally would
SharedPreferences.Editor editor = sharedPreferences.edit();
查看更多详情:https://android-developers.googleblog.com/2020/02/data-encryption-on-android-with-jetpack.html
官方文档:https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences
答案 2 :(得分:0)
如果担心可以从SharedPreferences读取令牌,一个好的经验法则是为存储的数据提供一定程度的加密。
此响应概述了一个加密数据的简单类: What is the most appropriate way to store user settings in Android application