首页 文章

在React Native中保存敏感数据

提问于
浏览
36

我正在构建一个React Native应用程序,我需要保存一些敏感数据,如令牌和刷新令牌 . 显而易见的解决方案是使用AsyncStorage保存该信息 . 问题是AsyncStorage的安全级别 .

AsyncStorage提供了一种本地存储令牌和数据的方法 . 在某些方面,它可以与LocalStorage选项进行比较 . 在完整的 生产环境 应用程序中,建议不要直接访问AsyncStorage,而是使用抽象层,因为AsyncStorage与使用相同浏览器的其他应用程序共享,因此从存储中删除所有项目的不当可能会影响相邻应用程序的功能 .

https://auth0.com/blog/adding-authentication-to-react-native-using-jwt/

在本机应用程序中,我会在 iOS 中查找 Keychain ,在 Android 中查看 private mode 中的 Shared Preferences .

对于我在React Native提供的文档中读到的内容:

在iOS上,AsyncStorage由本机代码支持,该代码将小值存储在序列化字典中,将较大值存储在单独的文件中 . 在Android上,AsyncStorage将根据可用内容使用RocksDB或SQLite .

https://facebook.github.io/react-native/docs/asyncstorage.html

他们从不谈论数据的安全性 .

这是为 Android (在 private mode 中使用 Shared Preferences )创建模块的最佳解决方案,为 iOS (使用 Keychain )创建另一个模块来保存敏感数据?或者使用提供的 AsyncStorage 方法是否安全?

4 回答

  • 59

    AsyncStorage 将键值对保存为Documents目录中的纯文本JSON文件 . It does not encrypt its contents .

    这是一个安全问题(至少在iOS上),因为有权访问设备的攻击者可以获取沙箱内容的转储,并且可以轻松提取通过 AsyncStorage 保存的任何数据 .

    以前在AsyncStorage.js的文档中没有明确说明,但它现在是:https://github.com/facebook/react-native/pull/8809

    另见:https://stackoverflow.com/a/38398114/1072846

  • 3

    刚刚深入研究React Native代码,我找到了答案 .

    Android

    React Native AsyncStorage 模块实现基于 SQLiteOpenHelper . 处理所有数据类的包:https://github.com/facebook/react-native/tree/master/ReactAndroid/src/main/java/com/facebook/react/modules/storage

    包含创建数据库的说明的类:https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/modules/storage/ReactDatabaseSupplier.java

    通过Android文档,应用程序创建的数据库保存在与关联应用程序相关的专用磁盘空间中,因此它是安全的 .

    就像您保存在设备内部存储上的文件一样,Android会将您的数据库存储在与关联应用程序相关的专用磁盘空间中 . 您的数据是安全的,因为默认情况下,其他应用程序无法访问此区域 .

    Source

    iOS

    在iOS中, AsyncStorage 值保存在序列化字典文件中 . 这些文件保存在应用程序 NSDocumentDirectory 中 . 在iOS中,所有应用程序都存在于 their own sandbox 中,因此一个应用程序的所有文件都是安全的,其他应用程序无法访问它们 .

    可以在此处找到处理 AsyncStorage 模块的iOS代码:https://github.com/facebook/react-native/blob/master/React/Modules/RCTAsyncLocalStorage.m

    我们可以看到here用于存储 AsyncStorage 保存的值的文件保存在 NSDocumentDirectory (在应用程序沙箱环境中) .

    每个应用程序都是一个岛屿iOS应用程序与文件系统的交互主要限于应用程序沙箱内的目录 . 在安装新应用程序期间,安装程序会为应用程序创建许多容器 . 每个容器都有特定的角色 . bundle容器保存app的包,而数据容器包含应用程序和用户的数据 . 数据容器进一步划分为许多目录,应用程序可以使用这些目录对数据进行排序和组织 . 该应用程序还可以在运行时请求访问其他容器 - 例如,iCloud容器 .

    Source

    Conclusion

    使用 AsyncStorage 来保存用户令牌是安全的,因为它们是在安全的上下文中保存的 .

    请注意,这仅适用于没有 root 的Android设备和没有 jailbreak 的iOS设备 . 另请注意,如果攻击者对设备有 physical access 且设备未受保护 . 他可以将设备连接到mac笔记本电脑和extract the documents目录,并查看文档目录下保存的所有内容 .

  • 3

    我真的建议你使用像react-native-keychain这样的库来存储react-native中的私人数据

    对于Android API级别:

    • 16-22使用Facebook Conceal

    • 23使用Android Keystore

    你可以像这样使用它:

    // 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);
      });
    
  • 2

    如果有人想要加密数据的额外步骤,您可能需要查看:https://github.com/oblador/react-native-keychain

    它在内部使用facebook conceal .

相关问题