设置 firebase 存储规则以监视 React Firebase 中的一个状态

setting firebase storage rule to watch for a piece of state in React Firebase

是否可以设置一个 firebase 存储规则来监视一个状态的值?

我没有为我的应用程序使用 firebase 身份验证,我只想使用存储桶来存储文件。我的应用程序中有一个状态变量:

  const [state, setState] = useState({
    currentUser: null,
    isAuthed: false
  });

如果用户通过身份验证,isAuthed 值将变为 true。因此是否可以编写如下所示的规则集:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if state.isAuthed === true;
    }
  }
}

您的 post 提出了两个问题:
如何将数据传递给存储规则?
如何在不使用 firebase 身份验证的情况下检查身份验证状态?

☉️将数据传递给存储规则

文件路径

您可以将文件保存到路径 /userfiles/authenticated/... 以表明该文件是由经过身份验证的用户上传的。在存储规则中,通过match子句访问路径:

match /userfiles/authenticated/{allPaths=**} {
  allow read, write: if true;
}

自定义元数据

上传文件时您可以设置自定义元数据this way:

const metadata = { customMetadata: { isAuthed: true } };
const uploadTask = uploadBytes(storageRef, file, metadata);

那么可以read the metadata在存储规则中:

match /{allPaths=**} {
  allow read, write: if request.resource.metadata.isAuth == true;
}

自定义声明或自定义令牌

Custom claims or custom tokens 允许以安全的方式将数据分配给用户,然后将此数据传递给存储规则。 自定义声明需要使用 firebase 身份验证,但自定义令牌允许您在不使用 firebase 身份验证的情况下从服务器分配令牌。 读取数据:

match /{allPaths=**} {
  allow read, write: if request.auth.token.isAuth == true;
}

正在检查身份验证状态

使用自定义令牌

确保只有经过身份验证的用户才能上传的最简单方法是通过自定义声明或自定义令牌,如上所述。

加密技巧

⚠️ 仅供娱乐,use at your own risks
让我们推出我们自己的加密协议,以一种安全的方式只允许上传给经过身份验证的用户。注意:这不会阻止读取访问,因为我们无法提供元数据。

1- 用户从您的服务器请求上传令牌:

const crypto = require("crypto");
const SECRET = "S3CRET"; // a secret shared by your server and security rules

// If the user is authenticated, send them this upload token:
const nonce = crypto.randomBytes(9).toString('base64');
const data = `${nonce},${filepath},${SECRET}`
const token = { nonce, hash: crypto.createHash('sha256').update(data).digest('base64') };

2- 如上所述,您通过文件路径或自定义元数据将上传令牌传递给存储规则

3- 在存储规则中,你 validate the hash:

match /{allPaths=**} {
  allow read: if true;
  allow write: if verifyHash(request, allPaths);
}

function verifyHash(request, path){
  let nonce = request.resource.metadata.nonce;
  let hash = request.resource.metadata.hash;
  let hash2 = hashing.sha256(nonce + "," + path + ",S3CRET")).toBase64();
  return hash == hash2; 
}

4- 利润:只有拥有上传令牌的用户才能上传文件,作为奖励,您还可以强制执行文件路径,还可以使用时间戳增强令牌,并强制执行某种速率限制。