如何在React中添加一个安全显示Firestore集合值的实时计数器?

huangapple go评论64阅读模式
英文:

How to add a live counter in react that displays a firestore collection value securely?

问题

目标: 在我的React Firebase网站上有一个实时计数器,显示我的YouTube频道的当前观看次数。

方法: 我通过调用YouTube API从Firebase云函数中检索观看次数,以保护我的API密钥。一旦我获取了数据,我使用另一个云函数来更新我的Firestore数据库中的观看次数集合(使用pubsub每60分钟)。然后,我在前端使用onSnapshot来监视这个集合并显示该值。

问题: 尽管这确实有效,但我每天都会收到来自Firebase的电子邮件,说我的Firestore数据库“存在不安全的规则”,因为“任何用户都可以读取整个数据库”。我不想为我的网站添加身份验证,但我希望实时计数器是完全安全的。有人知道如何实现引用Firestore数据库的实时计数器吗?

前端代码:

export default function Navbar() {
  const [count, setCount] = React.useState('');

  const unsub = onSnapshot(doc(db, "viewCount", "Count"), (doc) => {
    setCount(doc.get("View Count"));
  });
}

Firestore规则:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if true;
      allow write: if false; 
    }
  }
}

云函数:

/**
 * 每60分钟更新Firestore的观看次数的函数
 * 
 * @param - 
 * @returns - 无 
 */
exports.updateViewCount = functions.pubsub
  .schedule("every 60 minutes")
  .onRun((context) => {
    try {
      this.logCount(5);
      console.log("Count updated at:", new Date());
    } catch (error) {
      console.error("Error getting view count: ", error);
    }
  });



/**
 * 函数调用getViewCount获取YouTube观看次数
 * 
 * @param - 
 * @returns - Int: 观看次数 
 */
exports.logCount = functions
  .runWith({
    secrets: ["YOUTUBE_API"],
  })
  .https.onCall(async (data, context) => {
    const viewData = await getViewCount(
      process.env.YOUTUBE_API,
      process.env.YOUTUBE_CHANNEL_ID
    );
    const addData = await admin
      .firestore()
      .collection("viewCount")
      .doc("Count")
      .set({ "View Count": viewData })
      .then(() => {
        return viewData;
      })
      .catch((error) => {
        console.error("Error writing document: ", error);
      });
  });

总结:

  1. 这是否是在Firestore中实现不需要身份验证的实时计数器的正确方式?
  2. 如果是的话,如何更安全地实现这一点?如果不是,还有哪些其他选项?
英文:

Goal: To have a live counter on my React Firebase site that displays the current number of views on my youtube channel.

Method: I am retrieving the view count by calling the Youtube API from a firebase cloud function so that I can protect my API key. Once I have the data, I use another cloud function to update a view count collection in my firestore database (using pubsub every 60 minutes). I then monitor this collection using onSnapshot in my front-end and display the value.

Problem: While this does work, I get an email every day from Firebase saying my firestore database "has insecure rules" because "any user can read the entire database." I do not want to add authentication to my site, but I would like to have the live counter fully secure. Does anybody know how to have a live counter referencing a firestore database?

Front-end code:

export default function Navbar() {
  const [count, setCount] = React.useState('');

  const unsub = onSnapshot(doc(db, "viewCount", "Count"), (doc) => {
    setCount(doc.get("View Count"));
  });

Firestore rules:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if true;
      allow write: if false; 
    }
  }
}

Cloud functions

/**
 * Function updates Firestore view count every 60 minutes
 * 
 * @param - 
 * @returns - N/A 
 */
exports.updateViewCount = functions.pubsub
  .schedule("every 60 minutes")
  .onRun((context) => {
    try {
      this.logCount(5);
      console.log("Count updated at:", new Date());
    } catch (error) {
      console.error("Error getting view count: ", error);
    }
  });



/**
 * Function calls getViewCount to get Youtube View Count
 * 
 * @param - 
 * @returns - Int: View count 
 */
exports.logCount = functions
  .runWith({
    secrets: ["YOUTUBE_API"],
  })
  .https.onCall(async (data, context) => {
    const viewData = await getViewCount(
      process.env.YOUTUBE_API,
      process.env.YOUTUBE_CHANNEL_ID
    );
    const addData = await admin
      .firestore()
      .collection("viewCount")
      .doc("Count")
      .set({ "View Count": viewData })
      .then(() => {
        return viewData;
      })
      .catch((error) => {
        console.error("Error writing document: ", error);
      });
  });

To recap:

  1. Is this the right way to implement a live counter with firestore without authentication?
  2. If so: How can I do this more securely? If not: what other options are there?

答案1

得分: 2

要停止警告邮件,您只需要更改您的规则,以便不将 allow read: if true; 应用于整个数据库。您仍然可以将其应用于包含计数器的数据库部分。

service cloud.firestore {
  match /databases/{database}/documents {
    match /viewCount/Count {
      allow read: if true;
      allow write: if false; 
    }
  }
}

如果您的应用还使用其他文档和集合,您需要为它们添加规则。

英文:

To get the warning emails to stop, you just need to change your rules so that allow read: if true; isn't applied to the entire database. You can still apply it to the part of the database where the counter is.

service cloud.firestore {
  match /databases/{database}/documents {
    match /viewCount/Count {
      allow read: if true;
      allow write: if false; 
    }
  }
}

If you have other documents and collections that are being used by your app, you'll need to add rules for them too.

huangapple
  • 本文由 发表于 2023年2月14日 09:38:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75442738.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定