javascript - Firebase 用户已通过身份验证,那么为什么上传到存储被拒绝?

标签 javascript firebase react-native firebase-storage react-native-firebase

在一个react-native项目中,我同时使用两者 react-native-firebasefirebase sdk。 react-native-firebase 不允许使用 firebase 存储来上传图像 blob,这就是为什么我使用 vanilla Firebase javascript SDK 来完成此部分。为了区别起见,在我的代码和这篇文章中,我将 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 的方式有关。我在之前的测试项目中同时使用了两者,并且在 fork 项目 rn-fetch-blob 的帮助下成功运行(react-native-fetch-blob 的维护版本)/code>),但是我在测试时没有制定安全规则,所以...

有什么办法可以解决这个问题吗?

最佳答案

是的,您猜对了,您的 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 不应该在移动应用程序中使用,尤其是当它是 native 应用程序时,因为 firebase 会将客户端视为 Web 客户端,并且今后您将无法利用 firebase 中所有可能的移动功能,例如动态链接、推送通知和分析。

希望这有帮助!干杯!

关于javascript - Firebase 用户已通过身份验证,那么为什么上传到存储被拒绝?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59866411/

相关文章:

javascript - React 中未处理的 Promise 拒绝

reactjs - 如何保持 TypeScript 类型干燥

javascript - FabricJS Fluid 对齐网格

javascript - Twitter Bootstrap Carousel 跳过问题

android - OneSignal 导致 Google Play 服务版本发生变化

Angular 2 Route Guard/Auth Guard 安全

android - 尽管在使用 FirebaseStorage 时初始化 FirebaseApp,但仍获取 "Default FirebaseApp is not initialized in this process"

javascript - 在 ASP.NET MVC 中使用 jQuery 渲染局部 View

JavaScript 继承。如何扩展类

android - 为什么在安卓上安装后有两个应用图标?