什么可能使已注销的用户绕过 Firebase 默认存储规则并访问存储桶?

What might enable a logged-out user to bypass Firebase default Storage rules and access a Storage bucket?

我一直在尝试使用 Firebase 代码在我的 Windows 11 PC 和我的 Firebase 存储桶之间生成 upload/download 文件。一旦我让它工作,我意识到代码不包括登录。由于我使用的是默认的云存储规则,我本以为我的 upload/download 呼叫会被退回。

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
       allow read, write: if request.auth != null;
    }
  }
}

我清除了浏览器缓存并注销了 Google 和 Firebase 控制台,看看是否可以解决问题。它没有,也没有重新启动。但后来我发现代码在完全独立的机器上 运行 时出现了预期的错误,这让我大为欣慰。 运行 我的代码(现已部署到网络上)在这种情况下产生了预期的错误:

“糟糕 - 上传失败:错误 = FirebaseError:Firebase 存储:用户无权访问 'some-child'。(storage/unauthorized)”。

但问题仍然存在于我的开发 PC 上,所以我的问题是,是什么可能使 Firebase 进入绕过云存储规则的状态,即使没有登录也允许存储桶访问?

这是我正在使用的 (firebase v9) 代码(它允许我将我 PC 上的选定文件上传到存储桶中名为 'some-child' 的文件,然后将其下载到名为demo.txt 在我的下载文件夹中)。 :

import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.4.0/firebase-app.js';
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'https://www.gstatic.com/firebasejs/9.4.0/firebase-auth.js';
import { getStorage, ref, uploadBytes, getDownloadURL } from 'https://www.gstatic.com/firebasejs/9.4.0/firebase-storage.js';

const firebaseConfig = {
    ...
};
const firebaseApp = initializeApp(firebaseConfig);

const provider = new GoogleAuthProvider();
const auth = getAuth();

const storage = getStorage();
const storageRef = ref(storage, 'some-child');

window.onload = function () {

    document.getElementById('fileitem').onchange = function () { uploadFile() };
    document.getElementById('downloadbutton').onclick = function () { downloadFile() };

}

function uploadFile() {
    var file = document.getElementById('fileitem').files[0];
    uploadBytes(storageRef, file)
        .then((snapshot) => { 
            alert('Successful  upload');
        })
        .catch((error) => {
            alert('Oops - upload failed : error = ' + error);
        });
}

function downloadFile() {

    var file = getDownloadURL(ref(storage, 'some-child'))
        .then((url) => {
            // `url` is the download URL for 'some-child' and can be downloaded directly:
            const xhr = new XMLHttpRequest();
            xhr.responseType = 'text';
            xhr.onload = (event) => {
                const blob = xhr.response;
                const a = document.getElementById('downloadanchor');
                a.href = window.URL.createObjectURL(new Blob([blob], { type: "text/plain" }));
                a.download = "demo.txt";
                a.click();
                alert('Successful download');
            };
            xhr.open('GET', url);
            xhr.send();
        })
        .catch((error) => {
            alert('Oops - download failed : error = ' + error);
        });
}

当然有一个 html 前端。内容如下:

    <input id="fileitem" type="file"><br></br>
    <button id="downloadbutton">Download</button>
    <a id="downloadanchor" href="" download></a>

听起来您好像只让一个用户登录过一次,就再也没有退出过。 Firebase 保留用户凭据并在重新加载页面时恢复它们,然后将其与对数据库的调用一起发送。这通常正是您想要的,但在这里它似乎妨碍了您。

如果您不想使用身份验证,您可以 sign the user out 通过一次性调用 signOut`:

import { getAuth, ... } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});