未经认证的Firestore安全规则

时间:2019-10-18 14:21:35

标签: firebase google-cloud-firestore firebase-security

我将数据存储在Cloud Firestore数据库中。我的应用程序中的用户无需创建帐户即可获取数据,他们也可以在不登录的情况下写入数据。

Google每隔几天就会提醒我我的数据库不安全,任何人都可以滥用它。如何在不访问Auth变量的情况下改进它?

我的Firebase规则

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}

有没有一种方法可以使我的数据库更安全而不使用身份验证?

我的应用的逻辑:

我的数据库包含姓氏及其来源。如果有人输入名称,他将从数据库中获取来源。例如:“ Doe”->“墨西哥”。如果数据库中不存在姓氏,则调用API并将其值保存到数据库中。每个用户都需要读写权限。

我在这里可以做什么?

3 个答案:

答案 0 :(得分:2)

由于您需要写入的操作受到限制(仅插入新项目),因此您可以选择以下选项:

  • 您可以拒绝对最终用户客户端的写入,而可以将请求发送给完全执行所需操作的云功能(在验证输入或可能需要的其他任何检查,速率限制等之后)。云功能在通过管理访问权限运行时会忽略安全规则。

这是一个示例节点函数,它执行对实时数据库的写操作,并且在安全规则中的读和写均为错误时成功(您的关联package.json显然需要依赖firebase-admin和firebase-functions ):

def discover(request):
  company_staff = get_object_or_404(CompanyStaff, user=request.user)
  company = company_staff.company
  posts = Post.objects.filter(company=company, active=True)

您可能想了解firebase管理员SDK如何access control,但是默认情况下,在云功能中,您应该具有管理员权限。

  • 使用rules language仅允许创建操作。这消除了客户端更新或删除现有数据的能力。这不像以前的方法那么安全,但是对您来说可能没问题:
const functions = require('firebase-functions');

// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();

let db = admin.firestore();

// This pushes the "text" parameter into the RDB path /messages/(hash)/original
exports.addMessage = functions.https.onRequest(async (req, res) => {
    // Grab the text parameter.
    const original = req.query.text;
    // Push the new message into the Realtime Database using the Firebase Admin SDK.
    const snapshot = await admin.database().ref('/messages').push({original: original});
    // Respond to the user (could also be a redirect).
    res.send('got it: ' + snapshot.ref.toString());
  });

另外,请注意,此功能适用于Firestore(您正在使用),但不适用于实时数据库。

很显然,这两种方法都可能在某种程度上被滥用以将大量数据写入数据库,尽管前一种方法使您对允许的内容有更多的控制权(例如,您可以防止超过N个条目,或者防止超过Y个条目每个条目的字节数)。后者仍然允许任何人创建他们想要的东西。

答案 1 :(得分:2)

第一件事是从documentation开始。 强烈建议您了解规则可以执行的操作,并将其转换为应用程序的要求。

您现在为应用描述的内容过于模糊,无法制定出良好的规则。老实说,如果没有Firebase身份验证,则无法接受没有身份验证的数据库写操作,并且还避免了滥用,因为任何人都可以从Internet上的任何地方编写任何内容。如果有人发现您的“开放”数据库,这也可能会花费您大量资金。

答案 2 :(得分:1)

查看此文档。 https://firebase.google.com/docs/firestore/security/rules-structure。仅在您指定的集合中配置未经身份验证的用户的写入。

service cloud.firestore {
  match /databases/{database}/documents {

    // authentication required
    function issignedin() {
      return request.auth != null;
    }

    // authentication not required
    function notAuthenticated() {
      return request.auth == null;
    }

    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if notAuthenticated();

      // Applies to queries and collection read requests
      allow list: if notAuthenticated();
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if notAuthenticated();

      // Applies to writes to existing documents
      allow update: if notAuthenticated();

      // Applies to delete operations
      allow delete: if notAuthenticated();
    }
  }
}

考虑到

,如果调用API允许随意编写,则将是不安全的。 注意:如果您要引用的API是唯一可以编写的API,则必须仅将阅读配置为public

service cloud.firestore {
  match /databases/{database}/documents {

    // authentication required
    function issignedin() {
      return request.auth != null;
    }

    // authentication not required
    function notAuthenticated() {
      return request.auth == null;
    }

    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if notAuthenticated();

      // Applies to queries and collection read requests
      allow list: if notAuthenticated();
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if issignedin();

      // Applies to writes to existing documents
      allow update: if issignedin();

      // Applies to delete operations
      allow delete: if issignedin();
    }
  }
}