ReactNativeでFirebase JS SDKのユーザー情報が保存される場所を確認
ニッチな記事なので、メモ的な形式ですみません。
firebase-js-sdkの実装を確認
この辺りで環境ごとに使用するストレージの種類を定義している
https://github.com/firebase/firebase-js-sdk/blob/6b53e0058483c9002d2fe56119f86fc9fb96b56c/packages/auth/src/storage/factory.js#L79
https://github.com/firebase/firebase-js-sdk/blob/6b53e0058483c9002d2fe56119f86fc9fb96b56c/packages/auth/src/authstorage.js#L181
https://github.com/firebase/firebase-js-sdk/blob/6b53e0058483c9002d2fe56119f86fc9fb96b56c/packages/auth/src/utils.js#L679
環境を特定している処理を遡るとどこまでいくのかわからないけど、ともかくReactNative環境ではAsyncStorageを使用している。
fireauth.storage.AsyncStorage
https://github.com/firebase/firebase-js-sdk/blob/6b53e0058483c9002d2fe56119f86fc9fb96b56c/packages/auth/src/storage/asyncstorage.js
ユーザーの認証情報はこの辺りでJSON化してストレージに保存している。
https://github.com/firebase/firebase-js-sdk/blob/6b53e0058483c9002d2fe56119f86fc9fb96b56c/packages/auth/src/storageusermanager.js#L374
AsyncStorageの実装を確認
Android
AsyncStorageModule.java
https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/modules/storage/AsyncStorageModule.java
ReactDatabaseSupplier.java
https://github.com/facebook/react-native/blob/aee88b6843cea63d6aa0b5879ad6ef9da4701846/ReactAndroid/src/main/java/com/facebook/react/modules/storage/ReactDatabaseSupplier.java
SQLiteを使用している。
DB名はRKStorage
に、テーブル名はcatalystLocalStorage
なっているはず。
https://github.com/facebook/react-native/blob/aee88b6843cea63d6aa0b5879ad6ef9da4701846/ReactAndroid/src/main/java/com/facebook/react/modules/storage/ReactDatabaseSupplier.java#L25
iOS
RCTAsyncLocalStorage.mm
https://github.com/facebook/react-native/blob/652fa1b8d485ef86bc332116b9790ef61b905a0a/React/CoreModules/RCTAsyncLocalStorage.mm
https://github.com/facebook/react-native/blob/652fa1b8d485ef86bc332116b9790ef61b905a0a/React/CoreModules/RCTAsyncLocalStorage.mm#L81
writeToFileでAppのDocumentsディレクトリに保存しているのがわかる。
https://github.com/facebook/react-native/blob/652fa1b8d485ef86bc332116b9790ef61b905a0a/React/CoreModules/RCTAsyncLocalStorage.mm#L22
/Documents/RCTAsyncLocalStorage_V1
ディレクトリが用意される。
実機から内容を読み取ってみる
このような感じで、Firebase Authenticationでメールアドレス・パスワードによるログインをするだけの画面を用意し、確認してみました。
firebase.initializeApp
は割愛します。
import React, { Component } from 'react';
import { StyleSheet, Text, View, AsyncStorage } from 'react-native';
import firebase from './js/firebase';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
currentUser: null,
storageData: null
};
firebase.auth().onAuthStateChanged(async (currentUser) => {
console.log(currentUser);
this.setState({ currentUser });
if (currentUser && !this.state.storageData) {
const keys = await AsyncStorage.getAllKeys();
const values = await Promise.all(keys.map((key) => (AsyncStorage.getItem(key))));
this.setState({
storageData: JSON.stringify({ values, keys })
});
}
});
firebase.auth().signInWithEmailAndPassword('[email protected]', 'password');
}
render() {
const { storageData } = this.state;
return (
<View style={styles.container}>
<Text>{storageData}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
Android
端末をPCと繋いで、adb
を使ってアプリのデータを確認します。
$ adb shell
[ユーザ名]:/ $
アプリのデータは/data/data/[パッケージ名]
ディレクトリに入っています。
[ユーザ名]:/ $ cd data/data
[ユーザ名]:/data/data $ cd com.expofirebaseauthstoragetest
/system/bin/sh: cd: /data/data/com.expofirebaseauthstoragetest: Permission denied
[ユーザ名]:/data/data $
このようにそのままだとPermission denied
になってしまうので、アプリの権限でアクセスする必要があります。
参考:[Android] アプリの内部メモリを覗くとパーミッションでブロックされる
[ユーザ名]:/data/data $ run-as com.expofirebaseauthstoragetest
[ユーザ名]:/data/data/com.expofirebaseauthstoragetest $
ただし、リリースビルドのアプリではrun-asコマンドを使ってもアクセスできませんでした。
デバッグビルドかつandroid:debuggable="true"
の場合のみ内部ファイルにアクセスできるようです。
そのため、Expoを使わず素のReactNativeアプリで確認しています。
[ユーザ名]:/data/data/com.expofirebaseauthstoragetest $ cd databases/
[ユーザ名]:/data/data/com.expofirebaseauthstoragetest/databases $ ls
RKStorage
RKStorage
というデータベースが確認できました。とりあえずこれをコピーして、PCで中身を表示してみます。
[ユーザ名]:/data/data/com.expofirebaseauthstoragetest/databases $ cp RKStorage /mnt/sdcard
[ユーザ名]:/data/data/com.expofirebaseauthstoragetest/databases $ exit
$ adb pull /mnt/sdcard/RKStorage
SDカードのディレクトリは機種によって違うかもしれません。
adb pull
によりRKStorageをPCに移動できたら、DBの中身をDB Browser for SQLite等のソフトで確認します。
catalystLocalStorage
テーブルがあり、firebase:authUser:<API Key>:[DEFAULT]
キーにJSON形式でユーザー情報が入っているのがわかります。
ちなみに、この形式はWebでIndexedDBに入っているときの形と同様です。
iOS
端末とMacを繋げ、Xcodeでアプリを起動してFirebaseへのログインが完了したら、
iExplorerを使ってアプリ内のファイルを確認します。
開発時なので見れていますが、リリースビルドのアプリ内のディレクトリはinfo.plist
のUIFileSharingEnabled
(iTunesでファイルを共有できる設定)がYES
でない限り表示できないようです。例えばGmailなどはこんな感じ↓
先ほどのアプリのディレクトリを見てみると、
RCTAsyncLocalStorage_V1
ディレクトリにmanifest.json
と、ランダム文字列のように見える名前のファイルがあります。
manifest.json
の方はこんな感じ。
{"firebase:authUser:<API Key>:[DEFAULT]":null}
key/value形式になっていますが、ランダム文字列のような名前のファイルの方に実際のデータが入っていました。
このファイル名は上記のkeyをMD5でハッシュ化したもののようです。
{"uid":"xxxxxxxxxxx","displayName":null,"photoURL":null,"email":"[email protected]","emailVerified":false,"phoneNumber":null,"isAnonymous":false,"tenantId":null,"providerData":...
この最大文字数(1024字)を超えるものが別ファイルになり、それ以下の場合はmanifest.json
にそのまま値を入れるという実装になっています。
https://github.com/facebook/react-native/blob/652fa1b8d485ef86bc332116b9790ef61b905a0a/React/CoreModules/RCTAsyncLocalStorage.mm#L24
まとめ
Android
- ストレージの実装:SQLiteを使用
- DB名:
RKStorage
- テーブル名:
catalystLocalStorage
- アクセス制限:デバッグビルドかつ
android:debuggable="true"
のときのみ
iOS
- ストレージの実装:アプリのDocumentsディレクトリにファイルとして保存
-
/Documents/RCTAsyncLocalStorage_V1/manifest.json
にキーがあり、値は別ファイル(キーをMD5でハッシュ化したファイル名)に分かれている
- アクセス制限:デバッグビルド、あるいは
UIFileSharingEnabled
:YES
のときのみ
- DB名:
RKStorage
- テーブル名:
catalystLocalStorage
android:debuggable="true"
のときのみ-
/Documents/RCTAsyncLocalStorage_V1/manifest.json
にキーがあり、値は別ファイル(キーをMD5でハッシュ化したファイル名)に分かれている
UIFileSharingEnabled
:YES
のときのみAuthor And Source
この問題について(ReactNativeでFirebase JS SDKのユーザー情報が保存される場所を確認), 我々は、より多くの情報をここで見つけました https://qiita.com/mildsummer/items/c7a8a6a68844242c135f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .