Realm.io与Google Firebase的比较-安全性的观点

Realm.io与Google Firebase的比较-安全性的观点

本文是一系列简短文章之一,在这些文章中,我试图将Google Firebase产品与Realm Cloud平台的功能进行比较。 这两种产品都为移动应用程序提供了实时数据库功能。 两者都称为后端即服务(mBAAS)。 本文重点介绍Firebase和Realm Cloud之间的安全模型差异。

有关Realm.io的更多信息,请参见:

领域:在短时间内创建响应式移动应用程序

Realm是一个移动平台,是SQLite和Core Data的替代品。 建立离线优先,反应灵敏的移动体验…

境界

有关Google Firebase的更多信息,请访问:

火力基地

Firebase是Google的移动平台,可帮助您快速开发高质量的应用程序并发展业务。

firebase.google.com

在过去的七年中,我一直是iOS开发人员,自2015年以来,我广泛使用Firebase和Realm对象数据库。在加州圣塔莫尼卡市Needly,Inc担任移动架构师的同时,我帮助开发了Troop Team产品和WorkCoin市场产品。 这两种产品都依靠Firebase作为后端,并使用Realm作为本地对象数据库。 今天,我正在管理一家名为Cosync,Inc的新创公司,该公司正在围绕Realm Cloud平台开发协作平台。

Realm.io是一家有趣的公司。 它由Alexander Stigsen和Bjarne Christiansen于2011年成立,旨在为iOS和Android提供移动数据库。 该公司获得了风险投资,并在2015年成功筹集了2,000万美元。早期,基于云的移动应用程序需要缓存大量数据,而不必每次需要时都访问网络。 即使Apple和Google都在其开发框架中提供了本地数据库, 通过诸如Core Data之类的模块,Realm是解决此问题的第一个真正的跨平台解决方案。 此外,Realm已免费提供给开发社区,并且很容易在Objective C,Swift或Java中启动和运行,具体取决于移动设备。 我大约三年前开始使用它。 如今,全球Realm安装量已超过20亿,Realm开发人员超过10万。 在雷达下谈论! 他们只有33名员工。

Realm公司发布了名为Realm Platform的数据库的付费服务器版本,该版本在2017年是一个完整的后端即服务解决方案。它们的托管解决方案非常经济实惠,三个Realm实例的起价约为每月30美元-Realm实例是可以分配给单个移动应用程序的完整数据库。 在大多数情况下,这三个实例对应于移动应用程序的开发,登台和生产数据库。 定价基于已安装的客户端实例和带宽使用情况的组合。 像Google的Firebase一样,价格随使用情况而定。 但是与Firebase不同,客户可以根据需要选择将Realm Platform托管在自己的服务器上。 这非常强大,因为它可以满足许多对安全敏感的客户的需要,因为这些数据是由Google托管的,因此无法使用Firebase。 但是,更重要的是,大多数将Firebase用作后端实时数据库的应用程序开发人员也将Realm用作本地数据库来缓存网络数据。 这通常需要在Firebase和Realm之间在两个方向上都有些复杂的翻译层,每个开发人员都必须编写该翻译层。 如果开发人员使用Realm平台而不是Firebase,那么这个额外的翻译层(我可以证明是许多错误的来源)就消失了。

在安全性方面,Firebase和Realm均提供了锁定数据的机制。 这两种产品均在服务器端提供NoSQL实时数据库,以服务登录到各种客户端设备的用户。 简而言之,问题如下。 实时数据库由符合模式的表的集合组成,每个表包含许多属性,这些属性描述属于该表的对象的类型。 数据库实例包含许多注册用户,其中一些可以在客户端设备上登录,这些用户访问表中的对象。 安全性问题有两个方面:首先,属于表的对象必须遵守模式所指定的特定格式要求。 其次,必须根据用户的特权级别严格控制用户对此数据的访问。 第一个是验证问题,第二个是访问问题。

Firebase数据库本质上是一块巨大的JSON数据。 JSON数据的第一级包含数据库的最外面的表。 例如,考虑一个名为“ SimpleProjectManager”的应用程序,它具有三种类型的对象:用户,项目和任务。 Firebase数据库的结构如下:

Firebase规则确定结构和用户对Firebase JSON数据的访问权限。 规则本身在JSON中指定。 结构和验证以分层方式指定,在结构树的每个级别上指定数据是可读还是可写的。

对对象的属性验证非常简单; 每个属性均与相关的数据类型一起被阐明。 如果客户端写事务不符合规则指定的属性结构,则拒绝写事务,并且不更新数据库。 沿路径的每个点使用“ .read”或“ .write”条件表达式指定读写访问权限。 如果条件表达式的计算结果为true,则授予用户读取或写入访问权限。 在Firebase中,如果用户没有对该表的读取权限,则无法查询该表。 但是,如果用户具有对该条目的读取访问权限,则可以读取该表中的单个条目。

在Firebase中,权限从路径树的顶部开始向下分层地层叠。 本质上,这意味着,如果在父级别授予权限,则该权限将授予用户树中所有较低级别的权限。 换句话说,如果将许可授予父母,则将其自动授予孩子。 在Realm Platform中并非如此。 在实践中,尽管Firebase安全模型可以反映自由社会中赋予公民权利的方式,但是孩子与父母拥有相同的权利,甚至更多,但它并不适合向数据授予细粒度的特权。 在软件中,隔离和特权限制是安全系统的关键-考虑军队而不是大学校园。 程序员进行午夜班次操作,在Firebase中犯的一个常见错误是在文件顶部插入“ .read”,true语句,因为某些权限置换阻止了它们的更新—从而使系统完全不安全。

关于Firebase规则语言的另一个抱怨是这一切的复杂性。 在Firebase中,规则被编码为一组复杂的条件语句,根据身份验证用户的状态,这些条件语句的评估结果为true或false。 根据安全性要求,这些条件语句可能变得非常笨拙。 读取Firebase规则语句就像尝试解析XSLT样式表语句或调试LISP代码一样。 它们往往只是带括号的数据的一长串。 在2017年我为Needly,Inc工作的WorkCoin项目中,规范工作表的写入规则如下:

尽管从逻辑上看这似乎是正确的,但是另一个程序员很难真正验证所指定的安全性要求,更不用说调试它们了! 存在诸如BOLT编译器之类的第三方工具,它们可以简化Firebase安全规则的编写,但是由于它们可以转化为它们,因此复杂性永远不会消失。 实际上,Firebase项目团队中的一名程序员通常会负责安全规则,而其他人只是祈祷他/她做得正确。

Realm数据库的拓扑与Firebase的拓扑不同。 最高级别的机柜称为实例 ,它映射到单个应用程序。 实例具有唯一标识其服务器位置的URL。 在每个实例内部,都有一组领域和一组注册用户。 每个领域在实例中都有唯一的路径; 默认领域的路径称为“ / default”。 在每个领域内,可以存在许多属于它们的类和对象。 领域内对象的结构(即类的描述)通过JSON模式指定。 这类似于Firebase规则语言。 例如,用户类的Realm模式如下:

模式指定了数据的结构,它不处理验证,也不控制对数据的访问-允许用户读取,写入或修改。

与Firebase不同,Realm通过代码而不是通过管理控制面板来处理大多数功能。 话虽这么说,Realm确实提供了一个称为Realm Studio的工具,该工具向Realm数据库提供了一个交互式图形用户界面,这与Firebase控制台的方式非常相似。 Realm Studio是客户端桌面应用程序,而不是Web应用程序。

通常,Realm Platform应用程序将具有用iOS的Swift编写的客户端部分或用Android的Java编写的客户端部分,以及用Node.js编写的服务器部分。 服务器端的目的是对数据库执行验证和集中的后处理。 但是,从Realm的角度来看,服务器端本身就是另一个以管理用户身份登录的客户端。 实际上,服务器端部分实际上可以在台式计算机上运行,​​并且通常在开发应用程序时运行。 在Realm中,所有用户都是常规用户或管理用户; 后者可以完全访问实例中的所有内容。 通常只有一个管理用户,该用户在服务器端Node.js代码上运行。 从安全角度来看,移动客户端通常应仅支持普通用户。 初始化时,服务器端将为数据库上的用户设置所有访问控制权限。 与Firebase不同,设置访问控制权限是通过代码完成的。

领域提供了两种用于调节访问控制的机制。 第一个是路径级别权限,它适用于实例中的各个领域。 第二个是细粒度权限,该权限适用于类和单个对象。

路径级别权限控制实例中的哪些用户可以访问特定领域。 授予用户访问级别,该级别控制:

  • 阅读 –用户是否可以连接并阅读领域
  • 写入 –用户是否可以写入领域
  • 管理 –用户是否可以更改领域权限

在正常的应用场景中,每个用户都有一个默认领域(位于路径“ / default”)和私有领域。 用户创建私有领域时,它存在于名为/ / privateRealm的路径中。 用户登录后,可以使用路径/〜/ privateRealm访问该私有领域-代字号〜是用户ID的简写。 私有领域通常只能由用户和服务器访问。 永远不应授予其他用户访问其私人领域的权限。

从Realm的3.0版开始,该公司引入了细粒度权限的概念。 这是基于角色的许可协议,可将安全性和访问控制提高到一个全新的水平。 细粒度权限允许系统在对象级别上调节访问控制-因此,它们的名称为fine-grain 。 尽管可以在Firebase中circuit回实现,但是通过定义与数据库规则相关联的角色表,它不是内置功能。

细粒度权限基于角色的概念。 用户被分配了角色,这些角色被授予访问领域,类或对象的权限。 领域定义了许多预定义的角色,特别是角色“每个人”和每个用户的唯一角色,称为“ __User:”。 授予角色的权限类型包括:

  • canCreate
  • 可以阅读
  • canUpdate
  • canDelete
  • canQuery
  • canSetPermissions
  • canModifySchema

初始化时,服务器管理员将与“所有人”相关联的权限更改为非常严格,然后为其余用户定义多个角色及其访问权限。

在Realm中,精细权限在以下三个级别之一中运行:

  • 境界等级
  • 班级
  • 对象级别

就访问控制而言,Realm和Firebase之间的根本区别在于,使用Realm,可以将较低级别限制在一个级别授予的特权。 从概念上讲,这与Firebase相反,在Firebase中,在根级别授予的特权会自动授予较低级别的对象。 当运行一个自由和开放的社会时,Firebase的方法似乎是正确的,但是在实现软件安全性方面,军事上的分隔更加合适。 即使在现实生活中,仅仅因为您被允许进入银行也并不意味着您被允许进入金库-即使您必须被授予进入银行的权限才能进入金库。 在Firebase的三年编程中,我无法强调解决其级联特权政策有多么困难。

领域级别权限可以授予用户(或角色)读取领域的权限。 但是,可以在类级别,甚至在对象级别重写此权限。 阅读权实际上只是阅读的一种选择,这很重要。 此外,Realm在创建对象的写能力与更新或删除对象的写能力之间进行了区分— Firebase进行了这种区分,但仅在data()和newData()构造方面有所区别。 而且,Realm并不需要用户能够读取表中的所有对象才能查询它们。 对于无法访问的对象,查询将不会直接返回它们。 在Firebase中,表必须完全可读才能使查询成功-因此选择是公开所有内容或不公开任何内容。 最后,就安全性而言,Realm提供了一个元级别的构造,涉及其canSetPermissions和canModifySchema权限,该权限可以在精细级别授予用户是否允许他们修改领域,类或对象的权限。

Realm的一个缺点是,所有权限授予都是通过代码完成的,而不是通过某些管理控制台完成的。 隐含地,这需要程序员(而不是系统管理员)来管理应用程序数据库的权限和安全要求。 从维护和审核的角度来看,这都是一个缺点。 嵌入在代码中的安全性流程很难跟踪。 从好的方面来说,由于Realm的安全模型基于代码,因此可以利用编程语言的全部功能来解决问题-与Firebase复杂的条件语句语言不同。

总之,路径级别权限和细粒度权限的组合使Realm比Firebase更加容易编码和执行安全要求的系统。 在过去三年中对这两个系统都进行了编程,我觉得用Realm开发高度隔离的安全规则要比使用Firebase容易。