ReactNative MMKV和React Native Keychain存储本地数据
React Native存储方案对比与使用指南 本文对比了React Native中两种主流存储方案:MMKV和Keychain。MMKV作为AsyncStorage的替代方案,具有同步操作、高性能、线程安全、支持加密和无容量限制等优势,适合存储非敏感数据。Keychain则提供系统级安全加密,适合存储密码、token等敏感信息。文章详细介绍了两种方案的具体使用方法,包括基础操作、数据加密、多实例
目录
一、MMKV
为什么使用 MMKV 而不是 AsyncStorage?
1、MMKV 全面优于 AsyncStorage:
| 特性 | MMKV | AsyncStorage | 优势 |
|---|---|---|---|
| 性能 | ✅ 同步,毫秒级 | ❌ 异步,较慢 | 快 30-100 倍 |
| 线程安全 | ✅ 安全 | ⚠️ 部分安全 | 多线程无压力 |
| 加密 | ✅ 支持 AES | ❌ 不支持 | 数据更安全 |
| 容量 | ✅ 无限制 | ❌ 有 6MB 限制 | 存储更多数据 |
| TypeScript | ✅ 完美支持 | ⚠️ 一般 | 开发体验好 |
2、MMKV 极简教程
官方文档:https://github.com/mrousavy/react-native-mmkv
1)安装
# 安装
yarn add react-native-mmkv
# iOS (必做!)
cd ios && pod install
# Android自动链接,无需额外配置
2)基础使用
import { MMKV } from 'react-native-mmkv';
// 创建存储实例
const storage = new MMKV();
// 🟢 写入数据(同步)
storage.set('username', '张三');
storage.set('age', 25);
storage.set('isLoggedIn', true);
// 🟢 读取数据(同步)
const username = storage.getString('username'); // "张三"
const age = storage.getNumber('age'); // 25
const isLoggedIn = storage.getBoolean('isLoggedIn'); // true
// 🟢 删除数据
storage.delete('username');
// 🟢 检查是否存在
const hasUser = storage.contains('username');
// 🟢 获取所有键
const keys = storage.getAllKeys(); // ['age', 'isLoggedIn']
3)存储对象/数组
// 存储对象
const user = { name: '张三', age: 25 };
storage.set('user', JSON.stringify(user));
// 读取对象
const userString = storage.getString('user');
const userObj = JSON.parse(userString);
// 快捷方法
const setObject = (key, obj) => storage.set(key, JSON.stringify(obj));
const getObject = (key) => {
const str = storage.getString(key);
return str ? JSON.parse(str) : null;
};
4)加密存储(重要!)
// 创建加密存储
const encryptedStorage = new MMKV({
id: 'encrypted-storage',
encryptionKey: 'my-secret-key-123' // 至少16字符
});
// 使用方式相同
encryptedStorage.set('token', 'eyJhbGciOi...');
5)多存储实例
// 不同业务数据分开存储
const userStorage = new MMKV({ id: 'user-storage' });
const appStorage = new MMKV({ id: 'app-storage' });
const cacheStorage = new MMKV({ id: 'cache-storage' });
userStorage.set('profile', JSON.stringify({ name: '张三' }));
appStorage.set('settings', JSON.stringify({ theme: 'dark' }));
6)监听数据变化
// 监听特定键变化
const listener = storage.addOnValueChangedListener((key) => {
if (key === 'theme') {
console.log('主题改变了:', storage.getString('theme'));
}
});
// 移除监听
listener.remove();
7)实用封装示例
// storage.js - 统一管理
import { MMKV } from 'react-native-mmkv';
class Storage {
constructor() {
this.main = new MMKV();
this.secure = new MMKV({
id: 'secure',
encryptionKey: 'your-encryption-key-here'
});
}
// 用户相关
setUser(user) {
this.main.set('user', JSON.stringify(user));
}
getUser() {
const str = this.main.getString('user');
return str ? JSON.parse(str) : null;
}
// 安全存储
setToken(token) {
this.secure.set('access_token', token);
}
getToken() {
return this.secure.getString('access_token');
}
// 清空
clearAll() {
this.main.clearAll();
this.secure.clearAll();
}
}
export default new Storage();
// 使用
import storage from './storage';
storage.setUser({ name: '张三' });
storage.setToken('abc123');
8)常见场景
// 1. 登录状态管理
storage.set('isLoggedIn', true);
storage.set('userToken', 'xxx.yyy.zzz');
// 2. 应用设置
storage.set('theme', 'dark');
storage.set('language', 'zh');
storage.set('fontSize', 16);
// 3. 缓存数据
storage.set('lastUpdateTime', Date.now());
storage.set('cachedData', JSON.stringify(data));
// 4. 表单草稿
storage.set('draftPost', JSON.stringify({ title: '', content: '' }));
⚠️ 注意事项
-
加密key:生产环境要从安全的地方获取,不要硬编码
-
数据类型:注意使用对应的方法(getString/getNumber/getBoolean)
-
大对象:非常大的数据建议分拆存储
-
敏感数据:真正的密码、支付信息还是用Keychain
一句话总结:
MMKV = localStorage的同步版 + 加密功能 + 高性能
二、React Native Keychain
1、关键区别:加密 vs 系统级安全
一句话解释:
MMKV是应用层加密,Keychain是系统级安全。
敏感数据要用Keychain,因为系统更安全。
具体区别:
🔐 MMKV的加密(应用层)
// 加密存在App沙盒里
const storage = new MMKV({
encryptionKey: 'my-app-key-123' // 密码在App代码里
});
storage.set('token', 'abc123'); // 加密存储到App目录
风险:
-
加密密码在代码里 → 可能被反编译获取
-
App内可解密 → 越狱手机可读取
-
删除App数据就丢失
🛡️ Keychain的加密(系统层)
// 存到系统安全区域
await Keychain.setGenericPassword('token', 'abc123');
优势:
-
系统硬件加密 → 芯片级安全(Secure Enclave)
-
独立于App → 删App后数据还在
-
生物识别集成 → 可配指纹/面容ID访问
🚨 真实安全场景对比:
// ❌ MMKV存密码(不够安全)
// 密码:"myPassword123"
// 存储:AES加密后存App目录
// 风险:拿到手机→提取App文件→反编译得密码→解密// ✅ Keychain存密码(安全)
// 密码:"myPassword123"
// 存储:系统密钥链+硬件加密
// 风险:拿到手机→无密码/指纹→无法访问
📱 系统支持差异:
| 平台 | MMKV加密位置 | Keychain加密位置 |
|---|---|---|
| iOS | App沙盒文档 | 系统密钥链 + Secure Enclave |
| Android | App私有目录 | Android密钥库 + 硬件加密 |
📊 存储选择标准:
用MMKV存:
// 这些可以MMKV加密存
storage.set('user_preferences', 'dark_mode'); // ✅ 用户设置
storage.set('cached_data', '...'); // ✅ 缓存数据
storage.set('app_config', '...'); // ✅ 配置信息
用Keychain存:
// 这些必须用Keychain
await Keychain.setInternetCredentials(
'server',
'username',
'password' // 🔐 用户密码
);
await Keychain.setGenericPassword(
'access_token',
'eyJhbGciOiJ...' // 🔐 API令牌
);
⚠️ 安全审计要求:
-
金融类App → 必须用Keychain
-
医疗类App → 必须用Keychain
-
企业应用 → 建议用Keychain存凭证
简洁结论:
MMKV加密:防普通用户
Keychain加密:防黑客+合规要求
对于普通App: MMKV加密够用
对于敏感数据: 必须用Keychain
2、Keychain 极简教程
官方文档:https://github.com/oblador/react-native-keychain
1)安装
yarn add react-native-keychain
cd ios && pod install
# Android自动配置
2)基础使用
import * as Keychain from 'react-native-keychain';
// 🔐 存储敏感数据
await Keychain.setGenericPassword(
'username', // 服务标识(任意)
'password123' // 要存储的值
);
// 🔓 读取数据
const credentials = await Keychain.getGenericPassword();
if (credentials) {
console.log('账号:', credentials.username); // 'username'
console.log('密码:', credentials.password); // 'password123'
}
// 🗑️ 删除数据
await Keychain.resetGenericPassword();
3)存储API令牌(最常用)
// 存储token
await Keychain.setGenericPassword('access_token', 'eyJhbGciOiJ...');
// 读取token
const result = await Keychain.getGenericPassword();
const token = result ? result.password : null;
// token = 'eyJhbGciOiJ...'
// 删除token
await Keychain.resetGenericPassword();
4)进阶:带服务标识存储
// 存储多个凭证
await Keychain.setInternetCredentials(
'myapp.com', // 服务器地址(作为key)
'user@email.com', // 用户名
'userPassword123' // 密码
);
// 读取特定服务
const creds = await Keychain.getInternetCredentials('myapp.com');
// creds.username = 'user@email.com'
// creds.password = 'userPassword123'
// 删除特定服务
await Keychain.resetInternetCredentials('myapp.com');
5)生物识别(指纹/面容)
// 检查设备是否支持
const type = await Keychain.getSupportedBiometryType();
// type = 'Face' | 'Touch' | 'Biometrics' | null
// 存储并要求生物识别访问
await Keychain.setGenericPassword('user', 'secret123', {
accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_ANY,
accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
});
// 读取时验证生物识别
const result = await Keychain.getGenericPassword({
authenticationPrompt: {
title: '验证身份',
subtitle: '请验证以继续',
description: '使用面容ID验证',
}
});
6)实用封装
// secureStorage.js
import * as Keychain from 'react-native-keychain';
class SecureStorage {
// 存储令牌
async setToken(token) {
return await Keychain.setGenericPassword('access_token', token);
}
// 获取令牌
async getToken() {
const result = await Keychain.getGenericPassword();
return result ? result.password : null;
}
// 存储用户凭证(带生物识别)
async setUserCredentials(username, password, useBiometry = false) {
const options = {
service: 'myapp_user',
accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED,
};
if (useBiometry) {
options.accessControl = Keychain.ACCESS_CONTROL.BIOMETRY_ANY;
}
return await Keychain.setInternetCredentials('myapp.com', username, password, options);
}
// 清除所有
async clearAll() {
await Keychain.resetGenericPassword();
await Keychain.resetInternetCredentials('myapp.com');
}
}
export default new SecureStorage();
// 使用
import secureStorage from './secureStorage';
await secureStorage.setToken('your-jwt-token');
const token = await secureStorage.getToken();
7)实际使用示例
// 登录后保存
async function handleLogin(username, password) {
// 1. 调用登录API
const response = await loginAPI(username, password);
// 2. 存储token到Keychain
await Keychain.setGenericPassword('access_token', response.token);
// 3. 存储用户信息到MMKV(非敏感)
storage.set('currentUser', JSON.stringify(response.user));
}
// App启动检查登录状态
async function checkAuthStatus() {
const token = await getTokenFromKeychain();
if (token) {
// 自动登录
await fetchUserData(token);
} else {
// 跳转到登录页
navigate('Login');
}
}
// 退出登录
async function logout() {
// 1. 清除Keychain中的token
await Keychain.resetGenericPassword();
// 2. 清除MMKV中的用户数据
storage.delete('currentUser');
// 3. 跳转到登录页
navigate('Login');
}
⚠️ 注意事项
-
iOS需要配置:在Xcode中添加
Keychain Sharing能力 -
Android需要权限:添加
<uses-permission android:name="android.permission.USE_BIOMETRIC" /> -
模拟器测试:生物识别需要真机
-
错误处理:所有操作都要try-catch
一句话总结:
Keychain就是React Native的"保险柜",专存密码、token等敏感数据。
总结到此!
更多推荐



所有评论(0)