且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用Firebase ID令牌对Firebase存储进行身份验证

更新时间:2021-08-27 15:46:16

最后,我找到了答案的解决方案.解决方案是使用云功能.

Finally I found a solution to my answer. The solution is to use Cloud Functions.

Cloud Functions允许我们在nodejs环境中创建端点并使用AdminSdk,这是我们的Firebase项目的一部分.通过这种方法,我们可以向该端点发送一个http请求,这将检查接收到的带有请求的Token是否有效,如果有效,则保存文件.

Cloud Functions allows us to create endPoints and to use AdminSdk in a nodejs enviroment which is part of our firebase project. With this approach we can send an http request to that endpoint, this checks if the received Token with the request is valid and if it is, it saves the file.

这是功能代码:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const path = require("path");
const os = require("os");
const fs = require("fs");
const Busboy = require("busboy");

// Follow instructions to set up admin credentials:
// https://firebase.google.com/docs/functions/local-emulator#set_up_admin_credentials_optional
admin.initializeApp({
  credential: admin.credential.cert(
    __dirname + "/path/to/cert.json"
  ),
  storageBucket: "bucket-name",
});

const express = require("express");
const app = express();

// Express middleware that validates Firebase ID Tokens passed in the Authorization HTTP header.
// The Firebase ID token needs to be passed as a Bearer token in the Authorization HTTP header like this:
// `Authorization: Bearer <Firebase ID Token>`.
// when decoded successfully, the ID Token content will be added as `req.user`.
const authenticate = async (req, res, next) => {
  if (
    !req.headers.authorization ||
    !req.headers.authorization.startsWith("Bearer ")
  ) {
    res.status(403).send("Unauthorized");
    return;
  }
  const idToken = req.headers.authorization.split("Bearer ")[1];
  try {
    const decodedIdToken = await admin.auth().verifyIdToken(idToken);
    req.user = decodedIdToken;
    next();
    return;
  } catch (e) {
    res.status(403).send("Unauthorized");
    return;
  }
};

app.use(authenticate);

// POST /api/messages
// Create a new message, get its sentiment using Google Cloud NLP,
// and categorize the sentiment before saving.
app.post("/test", async (req, res) => {
  const busboy = new Busboy({ headers: req.headers });
  const tmpdir = os.tmpdir();

  // This object will accumulate all the fields, keyed by their name
  const fields = {};

  // This object will accumulate all the uploaded files, keyed by their name.
  const uploads = {};

  // This code will process each non-file field in the form.
  busboy.on("field", (fieldname, val) => {
    // TODO(developer): Process submitted field values here
    console.log(`Processed field ${fieldname}: ${val}.`);
    fields[fieldname] = val;
  });

  const fileWrites = [];

  // This code will process each file uploaded.
  busboy.on("file", (fieldname, file, filename) => {
    // Note: os.tmpdir() points to an in-memory file system on GCF
    // Thus, any files in it must fit in the instance's memory.
    console.log(`Processed file ${filename}`);
    const filepath = path.join(tmpdir, filename);
    uploads[fieldname] = filepath;

    const writeStream = fs.createWriteStream(filepath);
    file.pipe(writeStream);

    // File was processed by Busboy; wait for it to be written.
    // Note: GCF may not persist saved files across invocations.
    // Persistent files must be kept in other locations
    // (such as Cloud Storage buckets).
    const promise = new Promise((resolve, reject) => {
      file.on("end", () => {
        writeStream.end();
      });
      writeStream.on("finish", resolve);
      writeStream.on("error", reject);
    });
    fileWrites.push(promise);
  });

  // Triggered once all uploaded files are processed by Busboy.
  // We still need to wait for the disk writes (saves) to complete.
  busboy.on("finish", async () => {
    await Promise.all(fileWrites);
   
    // Process saved files here
    for (const file in uploads) {
      admin.storage().bucket().upload(uploads[file], function(err, file) {
        if (err) {
          res.status(403).send("Error saving the file.");
        }
        res.status(201).send("Saved");
      });
    }
  });

  busboy.end(req.rawBody);
});

exports.api = functions.https.onRequest(app);