我正在构建一个React Native应用程序,我需要保存一些敏感数据,如令牌和刷新令牌。显而易见的解决方案是使用AsyncStorage保存该信息。问题是AsyncStorage的安全级别。
AsyncStorage提供了一种本地存储令牌和数据的方法。它可以 在某些方面,与LocalStorage选项相比。在全 生产应用程序时,建议不要访问AsyncStorage 直接,而是使用抽象层,就像AsyncStorage一样 与使用相同浏览器的其他应用共享,因此 不明智的从存储中删除所有物品可能会损害 相邻应用程序的功能。
https://auth0.com/blog/adding-authentication-to-react-native-using-jwt/
在原生应用中,我会Keychain
中的iOS
和Shared Preferences
中私人模式中的Android
。
我在React Native提供的文档中读到的内容:
在iOS上,AsyncStorage由存储小值的本机代码提供支持 在序列化的字典中,在单独的文件中使用较大的值。上 Android,AsyncStorage将根据具体内容使用RocksDB或SQLite 是可用的。
https://facebook.github.io/react-native/docs/asyncstorage.html
他们从不谈论数据的安全性。
这是为Android
创建模块的最佳解决方案(在私有模式下使用Shared Preferences
),为iOS
创建另一个模块(使用 Keychain )保存敏感数据?或者使用提供的AsyncStorage
方法是安全的吗?
答案 0 :(得分:71)
只需深入研究React Native代码,我找到了答案。
<强>的Android 强>
React Native
AsyncStorage
模块实施基于SQLiteOpenHelper
。
处理所有数据类的包:https://github.com/facebook/react-native/tree/master/ReactAndroid/src/main/java/com/facebook/react/modules/storage
通过Android文档,应用程序创建的数据库保存在与关联应用程序相关的专用磁盘空间中,因此它是安全的。
就像您在设备内部存储中保存的文件一样, Android将您的数据库存储在与之关联的专用磁盘空间中 应用。您的数据是安全的,因为默认情况下此区域不是 其他应用程序可以访问。
<强>的iOS 强>
在iOS中,AsyncStorage
值保存在序列化字典文件中。这些文件保存在应用程序NSDocumentDirectory
中。在iOS中,所有应用程序都位于他们自己的沙箱中,因此一个应用程序的所有文件都是安全的,其他应用程序无法访问它们。
可以在此处找到处理AsyncStorage
模块的iOS代码:https://github.com/facebook/react-native/blob/master/React/Modules/RCTAsyncLocalStorage.m
我们可以看到here用于存储AsyncStorage
保存的值的文件保存在NSDocumentDirectory
下(在应用程序沙箱环境中)。
每个应用程序都是一个岛屿iOS应用程序与文件系统的交互 主要限于应用程序沙箱中的目录。中 安装新应用程序后,安装程序会创建一些 应用程序的容器。每个容器都有特定的角色。捆绑 容器保存应用程序的包,而数据容器保存 应用程序和用户的数据。数据容器是 进一步划分为应用程序可以使用的许多目录 排序和组织其数据。该应用还可以请求访问 其他容器 - 例如,iCloud容器 - 在运行时。
<强>结论强>
使用AsyncStorage
保存用户令牌是安全的,因为它们是在安全的上下文中保存的。
请注意,这仅适用于没有 root 的Android设备和没有越狱的iOS设备。另请注意,如果攻击者对设备物理访问且设备未受保护。他可以将设备连接到mac笔记本电脑和extract the documents目录,并查看文档目录下保存的所有内容。
答案 1 :(得分:4)
如果有人想要加密数据的额外步骤,您可能需要查看以下内容:https://github.com/oblador/react-native-keychain
它在内部使用facebook conceal。
答案 2 :(得分:3)
AsyncStorage
将键值对保存为Documents目录中的纯文本JSON文件。 它不会加密其内容。
这是一个安全问题(至少在iOS上),因为有权访问该设备的攻击者可以获取沙箱内容的转储,并轻易提取通过AsyncStorage
保存的所有数据。
以前在AsyncStorage.js的文档中没有明确说明,但它现在是: https://github.com/facebook/react-native/pull/8809
答案 3 :(得分:2)
我真的建议您使用像react-native-keychain这样的库来存储react-native
中的私人数据对于Android API级别:
你可以这样使用它:
// Generic Password, service argument optional
Keychain
.setGenericPassword(username, password)
.then(function() {
console.log('Credentials saved successfully!');
});
// service argument optional
Keychain
.getGenericPassword()
.then(function(credentials) {
console.log('Credentials successfully loaded for user ' + credentials.username);
}).catch(function(error) {
console.log('Keychain couldn\'t be accessed! Maybe no value set?', error);
});