Firebase 用户已通过身份验证,为什么上传到存储被拒绝?
Firebase user is authenticated, so why is uploading to storage denied?
在一个 react-native 项目中,我正在使用 both react-native-firebase
和 firebase
sdk。
react-native-firebase
不允许使用 firebase 存储上传图像 blob,这就是我使用 vanilla Firebase javascript SDK 来完成这部分的原因。为了区别起见,在我的代码和这个 post 中,我将 firebase javascript sdk 标识为 'FIREBASE',将 react-native-firebase
标识为 'firebase'.
我必须初始化我的 firebase 应用程序(即使 react-native-firebase
不需要它的功能,firebase
需要),App.js 构造函数和导入:
import * as React from 'react';
import AppNavigation from './src/navigation';
import { Provider } from 'react-redux';
import { store, persistor } from './src/store/index.js';
import firebase from 'firebase/app';
import { PersistGate } from 'redux-persist/integration/react';
export default class App extends React.Component {
constructor (props) {
super(props);
const firebaseConfig = {
apiKey: '{apiKey}',
authDomain: 'project-ID.firebaseapp.com',
databaseURL: 'https://project-ID.firebaseio.com',
projectId: 'project-ID',
storageBucket: 'project-ID.appspot.com',
messagingSenderId: '9999999999'
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
}
我在一个动作中实现了 firebase 和 FIREBASE(firebase 用于 auth/firestore,而 FIREBASE 用于存储):
import * as types from '../actions/types';
import RNFetchBlob from 'rn-fetch-blob';
import firebase from 'react-native-firebase';
import * as FIREBASE from 'firebase/app';
import 'firebase/storage';
import { Platform } from 'react-native';
const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs;
export const registerUser = (registration) => {
const { email, pass, username, img } = registration;
return (dispatch) => {
dispatch({ type: types.REGISTER_USER });
console.log('starting registration process...');
// check username is unique
firebase
.firestore()
.collection('users')
.where('username', '==', username)
.get()
.then((querySnapshot) => {
if (querySnapshot.empty !== true) {
// back to registration form
registrationFail(dispatch, 'Username already taken. Try again.');
console.log("Registrant's username already exists");
} else {
console.log('Registrants username is unique');
// continue with registration
firebase
.auth()
.createUserWithEmailAndPassword(email, pass)
.then((userCredential) => {
// successful user creation, now authenticated
// write to img storage
uploadImg(dispatch, img, userCredential.user.uid)
.then((imgUrl) => {
// on success, write to firestore
uploadImgSuccess(dispatch, 'Profile image upload successful...');
// write rest of data to firestore
firebase
.firestore()
.collection('users')
.add({
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
username: email,
uid: userCredential.user.uid,
profileImg: imgUrl,
email: email,
})
.catch((err) => {
console.log('Registration failed. Error: ' + err.message);
registrationFail(dispatch, err.message);
});
}
})
.catch((err) => {
// Image Profile NOT Uploaded
uploadImgFail(dispatch, err);
});
})
.catch((err) => {
// unsuccessful user creeation
registrationFail(dispatch, err.message);
});
}
})
.catch((err) => registrationFail(dispatch, err.message));
};
};
const uploadImg = async (dispatch, uri, uid, mime = 'image/png') => {
console.log('Starting image upload...');
dispatch({ type: types.UPLOAD_IMG, info: 'Uploading profile image...' });
const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
let uploadBlob = null;
// let downloadPath = '';
const imageRef = FIREBASE.storage().ref(uid).child('profileImg');
fs
.readFile(uploadUri, 'base64')
.then((data) => {
return Blob.build(data, { type: `${mime};BASE64` });
})
.then((blob) => {
uploadBlob = blob;
return imageRef.put(blob, { contentType: mime });
})
.then(() => {
uploadBlob.close();
return imageRef.getDownloadURL();
})
.then((url) => {
console.log('Returning Download URL: ' + url);
uploadImgSuccess(dispatch, 'Image upload successful...');
})
.catch((err) => {
uploadImgFail(dispatch, 'Image upload failed: ' + JSON.stringify(err));
});
};
但是当我通过 uploadImg()
时,我得到一个错误:
{
"code_": "storage/unauthorized",
"message":"Firebase Storage: User does not have permission to access 'someReference/someChild',
"serverResponse":{"Code":403, "message": "permission denied."}
}
这是 Firestore 规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
这是存储规则:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
我不明白发生了什么或为什么。用户在 react-native-firebase 的 createUserWithEmailAndPassword()
期间进行身份验证,甚至可以将数据上传到 Firestore。我唯一的猜测是,这可能与同时使用 firebase 和 FIREBASE 有关,或者与我使用 FIREBASE 设置 firebase 的方式有关。我在之前的测试项目中同时使用过这两个项目,并且它在分叉项目 rn-fetch-blob
(react-native-fetch-blob
的维护版本)的帮助下成功运行,但是我没有安全规则到位 bc 测试, 所以...
有什么解决办法吗?
是的,您猜对了,您的 FIREBASE
实例不知道 firebase
正在完成的身份验证,因为 firebase
处理本机方面,而 FIREBASE 只是一个JS 的东西。所以这两个实例都有自己的生活和自己的前景,具有自己的属性来识别用户并提供授权。
要解决此问题,请尝试通过 vanilla JS SDK 授权用户或使用 rn-firebase 完成整个任务。
我建议使用 react-native-firebase
,它对整个 firebase 堆栈有很好的支持。
https://rnfirebase.io/docs/v5.x.x/storage/reference/storage
编辑:
不应在移动应用程序中使用 Vanilla JS firebase SDK,尤其是当它是本机应用程序时,因为 firebase 会将客户端视为 Web 客户端,并且今后您将无法利用 firebase 中所有可能的移动设备,例如动态链接、推送通知和分析。
希望对您有所帮助!干杯!
在一个 react-native 项目中,我正在使用 both react-native-firebase
和 firebase
sdk。
react-native-firebase
不允许使用 firebase 存储上传图像 blob,这就是我使用 vanilla Firebase javascript SDK 来完成这部分的原因。为了区别起见,在我的代码和这个 post 中,我将 firebase javascript sdk 标识为 'FIREBASE',将 react-native-firebase
标识为 'firebase'.
我必须初始化我的 firebase 应用程序(即使 react-native-firebase
不需要它的功能,firebase
需要),App.js 构造函数和导入:
import * as React from 'react';
import AppNavigation from './src/navigation';
import { Provider } from 'react-redux';
import { store, persistor } from './src/store/index.js';
import firebase from 'firebase/app';
import { PersistGate } from 'redux-persist/integration/react';
export default class App extends React.Component {
constructor (props) {
super(props);
const firebaseConfig = {
apiKey: '{apiKey}',
authDomain: 'project-ID.firebaseapp.com',
databaseURL: 'https://project-ID.firebaseio.com',
projectId: 'project-ID',
storageBucket: 'project-ID.appspot.com',
messagingSenderId: '9999999999'
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
}
我在一个动作中实现了 firebase 和 FIREBASE(firebase 用于 auth/firestore,而 FIREBASE 用于存储):
import * as types from '../actions/types';
import RNFetchBlob from 'rn-fetch-blob';
import firebase from 'react-native-firebase';
import * as FIREBASE from 'firebase/app';
import 'firebase/storage';
import { Platform } from 'react-native';
const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs;
export const registerUser = (registration) => {
const { email, pass, username, img } = registration;
return (dispatch) => {
dispatch({ type: types.REGISTER_USER });
console.log('starting registration process...');
// check username is unique
firebase
.firestore()
.collection('users')
.where('username', '==', username)
.get()
.then((querySnapshot) => {
if (querySnapshot.empty !== true) {
// back to registration form
registrationFail(dispatch, 'Username already taken. Try again.');
console.log("Registrant's username already exists");
} else {
console.log('Registrants username is unique');
// continue with registration
firebase
.auth()
.createUserWithEmailAndPassword(email, pass)
.then((userCredential) => {
// successful user creation, now authenticated
// write to img storage
uploadImg(dispatch, img, userCredential.user.uid)
.then((imgUrl) => {
// on success, write to firestore
uploadImgSuccess(dispatch, 'Profile image upload successful...');
// write rest of data to firestore
firebase
.firestore()
.collection('users')
.add({
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
username: email,
uid: userCredential.user.uid,
profileImg: imgUrl,
email: email,
})
.catch((err) => {
console.log('Registration failed. Error: ' + err.message);
registrationFail(dispatch, err.message);
});
}
})
.catch((err) => {
// Image Profile NOT Uploaded
uploadImgFail(dispatch, err);
});
})
.catch((err) => {
// unsuccessful user creeation
registrationFail(dispatch, err.message);
});
}
})
.catch((err) => registrationFail(dispatch, err.message));
};
};
const uploadImg = async (dispatch, uri, uid, mime = 'image/png') => {
console.log('Starting image upload...');
dispatch({ type: types.UPLOAD_IMG, info: 'Uploading profile image...' });
const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
let uploadBlob = null;
// let downloadPath = '';
const imageRef = FIREBASE.storage().ref(uid).child('profileImg');
fs
.readFile(uploadUri, 'base64')
.then((data) => {
return Blob.build(data, { type: `${mime};BASE64` });
})
.then((blob) => {
uploadBlob = blob;
return imageRef.put(blob, { contentType: mime });
})
.then(() => {
uploadBlob.close();
return imageRef.getDownloadURL();
})
.then((url) => {
console.log('Returning Download URL: ' + url);
uploadImgSuccess(dispatch, 'Image upload successful...');
})
.catch((err) => {
uploadImgFail(dispatch, 'Image upload failed: ' + JSON.stringify(err));
});
};
但是当我通过 uploadImg()
时,我得到一个错误:
{
"code_": "storage/unauthorized",
"message":"Firebase Storage: User does not have permission to access 'someReference/someChild',
"serverResponse":{"Code":403, "message": "permission denied."}
}
这是 Firestore 规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
这是存储规则:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
我不明白发生了什么或为什么。用户在 react-native-firebase 的 createUserWithEmailAndPassword()
期间进行身份验证,甚至可以将数据上传到 Firestore。我唯一的猜测是,这可能与同时使用 firebase 和 FIREBASE 有关,或者与我使用 FIREBASE 设置 firebase 的方式有关。我在之前的测试项目中同时使用过这两个项目,并且它在分叉项目 rn-fetch-blob
(react-native-fetch-blob
的维护版本)的帮助下成功运行,但是我没有安全规则到位 bc 测试, 所以...
有什么解决办法吗?
是的,您猜对了,您的 FIREBASE
实例不知道 firebase
正在完成的身份验证,因为 firebase
处理本机方面,而 FIREBASE 只是一个JS 的东西。所以这两个实例都有自己的生活和自己的前景,具有自己的属性来识别用户并提供授权。
要解决此问题,请尝试通过 vanilla JS SDK 授权用户或使用 rn-firebase 完成整个任务。
我建议使用 react-native-firebase
,它对整个 firebase 堆栈有很好的支持。
https://rnfirebase.io/docs/v5.x.x/storage/reference/storage
编辑:
不应在移动应用程序中使用 Vanilla JS firebase SDK,尤其是当它是本机应用程序时,因为 firebase 会将客户端视为 Web 客户端,并且今后您将无法利用 firebase 中所有可能的移动设备,例如动态链接、推送通知和分析。
希望对您有所帮助!干杯!