通过Firebase身份验证设置文件上传限制并在中间没有服务器的情况下存储?

时间:2016-11-09 17:50:30

标签: javascript firebase firebase-authentication firebase-security firebase-storage

我正在了解Web应用中的Firebase身份验证和存储。我的想法要求用户通过Firebase登录,然后上传图片。

我可以看到这可以通过Firebase身份验证和存储实现。但是,我想限制他们可以上传的文件数和文件大小。

是否可以在Firebase控制台(或其他位置)内控制上传?在查看了JavaScript示例之后,我看到了如何将文件放入,我可以想象编写代码来查询Firebase以获取用户的上传计数,然后限制客户端,但当然,这是一种完全不安全的方法。

如果我将此作为单页应用程序托管在GitHub页面上,我想知道是否可以在不涉及服务器的情况下设置这些限制。或者,我是否需要通过服务器代理我的上传内容,以确保我从不允许用户上传超过我打算使用的内容?

3 个答案:

答案 0 :(得分:4)

您可以通过Firebase Storage's security rules限制用户上传的内容。

例如,这(来自链接的文档)是一种限制上传文件大小的方法:

service firebase.storage {
  match /b/<your-firebase-storage-bucket>/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

但是这些规则目前无法限制用户可以上传的文件数量。

我想到的一种方法是使用固定文件名。例如,如果将允许的文件名限制为1..5,则用户只能存储五个文件:

match /public/{userId}/{imageId} {
  allow write: if imageId.matches("[1-5]\.txt");
}

答案 1 :(得分:1)

如果您需要每用户存储验证,解决方案有点棘手,但可以完成。

Ps。:您需要使用云功能生成Firebase令牌,但服务器不会在中间进行上传...

https://medium.com/@felipepastoree/per-user-storage-limit-validation-with-firebase-19ab3341492d

答案 2 :(得分:0)

一种解决方案可能是使用Admin SDK来根据每天保存上载次数的Firestore文档更改存储规则。

假设您有一个userUploads/uid字段为uploadedFiles: 0lastUploadedOn的firestore集合/文档。

现在,一旦用户将文件上传到Firebase Storage(假设在限制范围内且没有错误),您就可以触发Cloud Function,该功能将读取userUploads/uid文档并检查lastUploadedOn字段是否为早期版本date(日期),而不是当前上传文件的日期,如果是,则将uploadedFiles设置为1,并将lastUploadedOn更改为上载日期时间。否则,增加uploadedFiles的计数并将lastUpdateOn更改为当前日期时间。一旦uploadedFiles的值变为10(您的限制),您就可以使用Admin SDK更改存储规则。请参见示例here。然后,在userUploads/uid文档中将计数更改为0。

但是,有一些警告。规则的更改可能需要一些时间,并且该规则应该没有合法的异步工作正在处理中。来自Admin SDK

Firebase安全规则需要数分钟才能完全部署。使用Admin SDK部署规则时,请确保避免竞争条件,在这种情况下,您的应用立即依赖尚未完成部署的规则

我自己还没有尝试过,但是看起来可以用。再三考虑,改变规则以允许写入可能会很复杂。如果用户在第二天(规则更改后)上载,则上载错误处理程序可以触发另一个云功能以检查是否为合法请求,将规则更改回正常状态,并在一段时间后再次尝试上载,但是它将是非常糟糕的用户体验。另一方面,如果您使用计划程序云功能每天检查userUploads/uid文档并重置值,则可能会很昂贵(每月每百万名用户18美元,读取$ 0.06 / 100K),并且如果用户处于不同的时区,对于大多数用户而言,可能无关紧要,这取决于他们是否经常上传。此外,规则有局限性

  • 序列化时,规则必须小于64 KiB的UTF-8编码文本
  • 一个项目最多可以有2500个已部署的规则集。达到此限制后,您必须先删除一些旧规则集,然后再创建新规则集。

因此,针对大型用户群的每个用户规则都可以轻松达到此限制(除其他规则外)。

也许最佳解决方案可能是使用Auth Claims。如果用户具有特定的auth声明令牌(例如canUpload: false),则最初具有拒绝写入规则。然后在上传时触发的云功能中,当用户达到限制时附加此声明。这将是实时的,因为它会立即阻止用户,这与Admin SDK规则部署延迟相反。

要删除身份验证声明:

  1. 通过上载错误处理程序中的另一个云功能检查lastUploadedOn是否已更改,从而删除了声明
  2. 在上传之前检查一个单独的云函数,该函数检查用户是否具有身份验证声明,并且lastUploadedOn是较早的日期,然后删除声明
  3. 此外,在登录过程中,如果lastUploadedOn早于今天,则可以对其进行检查和删除,但是它的效率低于2,因为在用户甚至不上传任何内容的情况下,它都构成了在Firestore上不必要的读取操作< / li>

在2中,如果客户端尝试跳过呼叫并具有auth声明,则他/她将无法按照安全规则阻止的方式进行上传。否则,如果没有auth声明,则他/他将通过正常过程。

注意:需要将更改身份验证声明推送到客户端。请参见此doc