我很确定这是一个愚蠢的主意,但我想知道为什么,所以请耐心等待。从内部数据库到内部数据库。客户通过某种加密连接使用某种凭据向Web服务授权,Web服务将验证数据并针对后端数据库执行查询,然后将结果返回给客户端。

总而言之,这只是直接与数据库进行交互的一种较差的方式:几乎没有人完全实现REST规范,而且迟早您总会以自制的通用过滤,排序或分页-尽管SQL已经支持所有这些功能。这具有很多优点:


客户端必须使用客户端证书对连接进行加密
我们可以使用服务器内置的访问控制,也可以仅针对每个客户使用分片数据库>(My-)SQL权限非常精细,因此我认为不应有任何明显的安全问题
性能应该更好,因为我们跳过了整个HTTP通信和Web应用程序代码
新功能与数据库迁移有关,所有内容都反映在架构中多个模式版本,尽管我认为谨慎的弃用(也许还有客户端SDK)应该将影响降到最低。

由于似乎没有人这样做,所以肯定存在我忽略的安全风险。为什么我们不能为客户提供公共SQL访问?可能出什么问题了? (请记住,这只是出于好奇而产生的思想实验)

评论

我不确定我是否理解您的问题,但我想这是设计问题。您的想法可能在某些简单情况下可行,但在更复杂的应用程序中,很快就会变得一团糟(难看或不可行)。

嗨,莫里兹。我已将您的问题标题编辑为实际问题。如果您不喜欢我的更改,欢迎您将其回滚或自己编辑!

作为参考,实际上在很多情况下人们都这样做,尽管在较旧的软件中这种情况更为常见。在某些情况下,我不得不打开直接的数据库访问权限,因为这是某些关键和较旧的业务软件支持的唯一集成。通常在那种情况下,我不会提供完整的数据库访问权限,甚至不会访问我的应用程序使用的表。取而代之的是,我保留了专用的表来存储应用程序的消耗量,这些表仅在需要发送数据时填充,而其他表则用于写入数据,我会定期检查这些更改。

也考虑使用CQRS代替CRUD。我之所以追求CQRS,是因为它在谈论数据时会产生不同的心理影响。 (踩这个,踩那个..带来不必要的重量)

GraphQL解决了许多此类问题。

#1 楼

TL,DR:不要。


(My-)SQL权限非常精细,所以我想应该不会出现任何明显的安全问题


即使在记录级别获得许可,它也确实易于扩展。如果用户在一个表上具有不受限制的SELECT,则他们可以选择该表上的任何记录,甚至包括那些不属于它们的记录。薪水表会很糟糕。如果任何用户使用DELETEUPDATE,他们可能会忘记WHERE子句,然后您的表就会出现。即使是DBA也会发生这种情况,那么为什么用户不会发生这种情况呢? br />
您将放弃使用应用程序来验证,过滤,授予和拒绝访问的所有安全性,审核,过滤和非常精细的权限控制。通常,在事务上花费的大部分时间是数据库处理查询。应用程序代码少于此数目,并且您将不会删除HTTP通信,而只是将其替换为SQL通信。 schema


这就是为什么如此多的人使用“电子表格作为数据库”的原因。当您需要协调来自多个来源的数据时,这是一场噩梦。


为用户提供了强大的查询功能,而无需付出任何额外的努力


就像将强大的引擎安装在骨架上,用螺栓固定在位子,并参加比赛。没有多余的重量使汽车减速,因此速度非常快!

这里也是一样。当然,它是快速而强大的,但是没有应用程序提供的安全措施,没有会话,记录级访问控制,“用户做他们允许做的事情”或审计。Web应用程序上最常见的漏洞之一是SQL注入,您正在向用户提供SQL控制台。您给了他们各种各样的枪支,许多子弹,还有脚,手,头……其中有些人不喜欢您。

评论


评论不作进一步讨论;此对话已移至聊天。

–Rory Alsop♦
20-04-21在12:17

虽然问题是用mysql标记的,但它看起来并不像MySQL特定,所以让我添加一些注释。 PostgreSQL,SQL Server和Oracle确实具有行级(记录级)安全性,因此它们似乎更适合此类任务。视图也可以用于MySQL。

–亚历山大·里赫利茨基(Alexander Ryhlitsky)
20年5月7日在8:53

#2 楼

有趣的问题。从理论上讲,这可以安全地完成。 MS-SQL可以通过加密来保护连接,对用户进行身份验证,并提供细粒度的权限和其他安全功能,例如审核。直接访问数据库,因此数据库安全控制是主要的安全机制。这往往做得不好,例如,所有用户以admin身份使用应用程序中的硬编码密码进行连接。但这可以做得很好。

一个主要问题是特权升级缺陷。数据库API极其复杂,呈现出巨大的攻击面,并且这些协议是为提高速度而设计的,而且这些协议过时并且没有经过Internet加固。例如,Oracle有数百个特权升级漏洞。但是,在这方面,MS-SQL是更好的数据库之一。您还可以通过锁定用户权限来减少攻击面。

从结构上来说,公开一个允许通用查询并应用安全限制的接口非常有意义。在某种程度上,随着REST API获得诸如自定义查询之类的功能,人们正在重新发明轮子。

能否做到这一点很大程度上取决于与用户的关系。如果这些客户是具有合同关系的付费客户,那么在某种程度上要比随机的Internet用户更受信任,可以使用此体系结构。尤其是当不同的客户端隔离在单独的数据库上时。小心行走。在这种情况下,即使您要仔细考虑风险和收益,也可能会因此受到批评。如果您正在运行带有匿名注册的Web扩展服务,则可以避免这种情况。尽管值得注意的是,大多数云平台提供商确实提供了将数据库端口公开给客户端的功能。

评论


刚刚意识到您说MySQL不是MS-SQL,但是大多数情况下

–paj28
20-4-17的14:27

应该注意的是,可以通过将实际表包装在视图中并使用更新触发器和更新的存储过程来提供API。这样,如果基础架构发生更改,则可以更新定义,以便在添加包含新功能的新视图时,旧查询仍然有效。它是否比数据库顶部的单独服务更好,取决于查询和高级操作的相对复杂性。

– Jan Hudec
20-04-18在20:47

@JanHudec,但实际上,如果您让用户能够编写自己的查询,则您几乎没有机会确保所有“旧查询”都能正常工作,因为您不知道它们是什么。人们可以做非常愚蠢的事情。

–尼尔森
20-04-19在5:26

@Nelson,如果仅授予用户访问视图的权限,则可以通过将视图的定义调整为用户看不见的基础表中的任何更改,来保持他们看到的架构不变。您也不知道查询是什么,这也不是真的,因为您会在慢速查询日志中看到慢速查询,并且可以在需要检查查询时启用完整查询日志。

– Jan Hudec
20-4-19的11:17

@gerrit-我对此没有任何数字。非正式地,它变得不那么普遍了。部分原因是胖客户端可能会使用Web服务后端-微软20年来一直在推动这一目标。但是,此外,内部应用程序现在通常是Web应用程序。当然,您仍然可以获得一些直接的数据库胖客户端。几年前我换了工作,所以三年来没有做任何内部测试。

–paj28
20-4-19在21:28



#3 楼

我已经构建了RESTful接口,并为客户提供了直接的SQL访问。

这里的问题是,这个问题从根本上来说是有缺陷的:后端开发人员所做的就是通过HTTP为
客户提供CRUD访问,本质上是将数据映射到内部
内部数据库中。


我所做的很大一部分。让我们将其简化为4个任务RE数据访问:


验证传入的数据。
身份验证,授权和日志记录。
公开有限的功能集。
提供对用户敏感的API。

数据库通常不提供工具根据这些任务的需要执行此操作。例如,我可能想:


使用外部服务验证传入的数据。
使用OAuth提供身份验证,并使用角色提供对特定行的访问。然后,我有一些要根据角色/数据访问权限写的特定日志。
我可能只想公开某些报告(例如,出于性能(例如DoS)或业务原因)的信息。这不是我大多数客户大多数时候想要的格式。

虽然我确定在某些情况下都有一些具有某些功能的数据库...通常大多数数据库都不支持大多数情况,因为它们是数据库,因此并非旨在处理业务逻辑。

以上所述,在某些情况下,客户端需要数据库级访问-在这种情况下,您会找到确实提供直接访问的解决方案。没有什么可以阻止这种情况的发生-这只是典型现象。

评论


所有主要数据库都有存储过程,您可以在其中基本上对所需的任何业务逻辑进行编程。它们的主要优点是它们在事务内部运行;通过rest api进行交易往往很难看。但是您在那里当然受到更多限制(只有PostgreSQL可以从存储过程中运行的语言才是不错的选择)。

– Jan Hudec
20-4-18在20:57



@JanHudec虽然存储过程和视图是对应用程序的很好补充,但不是用SQL查询+存储过程代替REST API只是将工作推到了一层?无需为所有业务逻辑编写REST端点,而是为所有业务逻辑编写存储过程。但是现在您的用户还可以运行他们想要的任何其他查询;速度慢,阻止查询和呼啸声,有人在更新时忘记了where子句。

–施韦恩
20-4-18在22:35



@Schwern,不;层是由它包含的逻辑定义的,因此它只是使用不同的技术来实现该层。它不允许(必须)允许用户进行任何其他查询或有风险的更新,因为您只授予他们通过视图读取,调用存储过程以及通过存储过程或具有实现检查的更新触发器的视图进行更新的权限。该层应该仍然存在,只是现在它是在数据库引擎中实现的,而不是作为单独的服务实现的。这取决于哪种API更好地表达所需的操作。

– Jan Hudec
20-04-18在22:52

@ NPSF3000,对于某些应用程序有意义,对于其他应用程序则没有意义。对于主要以数据为中心的应用程序,通常需要将确保一致性的逻辑放入数据库中,然后将负责工作流各个部分(报告,导入,导出等)的组件独立地连接到数据库。 (结束,例如让客户自己实现其中的一些)。对于其他人来说,拥有一个其他所有内容都可以通过的前端服务更有意义。因此,我同意这是应有的问题,但在某些情况下答案是肯定的。

– Jan Hudec
20-04-19在17:43

@ NPSF3000,您会想到一种特定的应用程序,对于这些应用程序,将逻辑放入存储过程是错误的。但是,并非所有的应用程序都是这样。一个主要功能是簿记(会计,ERP等)的系统不需要扩展,因为使用它的人数有限,但约束复杂且操作复杂(导入内容,将其与其他各种记录匹配,并且仅当(匹配,提交),使用数据库工具更容易表达。否则,您最终只会像问题中那样包装查询堆。

– Jan Hudec
20 Apr 19 '21:07

#4 楼

性能

您说性能应该“更好”,只是现在您刚刚授予了恶意行为者完全破坏数据库性能的权限。当然,他们必须进行身份验证,但是“恶意”演员也可以是“天真,无能”的合法用户。当用户开始在他们可以找到的所有表上运行外部联接,数据库中每个未索引字段上的where子句以及计算上昂贵的计算字段时,您将怎么办?除非您的数据库很小,否则您将面临这种风险。最常见的结果。并非每个服务都可以执行此操作,因为某些服务被明确设计为提供完全一致的读/写访问权限。但是许多是只读的,可以忍受一些延迟。更新一致性。如果这些服务使用内存缓存(如mecached,redis等),则其速度实际上比直接DB访问快数千倍。

验证

除非您在每个需要某种业务规则验证的表,直接访问都是破坏完整性的好方法。哦,那是一个有人在其中写字母字符的邮政编码字段?没问题。电话号码字段包含字母?精细。货币字段包含逗号和分号?也许有人试图通过逻辑黑客给自己免费奖金。您是否真的相信每个单用户都可以执行与您的Web应用相同的验证级别?您应该退出编码并成为牧师,因为您的信仰水平令人难以置信。

维护

有时,您需要使数据库脱机以进行重大维护。发生这种情况时,缓存Webapp至少可以继续为读取提供服务,但是在整个用户社区中都有直接访问的麻烦。有时您想将数据库迁移到功能更强的服务器上。那是什么?您在让所有用户同时切换其连接字符串时遇到麻烦吗?有时您想切换到群集。哦,那些硬编码的连接字符串现在真的在@ $$中咬你了,不是吗?安全性是否只是因为端口更新了防火墙规则而要求您切换端口?嗯...是时候通知所有客户他们的连接字符串需要更新了。

结论

如果您打算从来没有几个或更多客户几千行,并且您确定您的数据库/应用程序永远都不会超出此玩具大小,因此直接访问就是Just Fine(TM)。另一方面,如果您的数据库有一天可能会超出其当前的版本,或者您想要进行涉及重组,调整规模或重新定位的大型迁移,那么您将非常幸运,因为您拥有那一层可以节省的间接层您的培根,并带来可扩展的高性能解决方案的所有优点。

评论


对于传统的服务器数据库而言,情况不一定如此,但如果您使用诸如BigQuery或Aurora之类的SaaS大​​数据数据库之一,则该恶意性能问题可能会导致您能够非常迅速地向您的公司开出大笔账单。我曾经遇到一个意想不到的2000美元账单,因为内部客户对有关数据的存储很幼稚。如果他们是恶意的,在我们注意到之前,他们可能已经赚了20-30,000美元。

–user1937198
20-04-17在23:54

@ user1937198公平地说,至少就BigQuery而言,您可以共享数据,同时让客户使用自己的计费项目付费使用。 BigQuery是共享大规模SQL数据的一种好方法-但要清楚,这与OP的要求有很大不同。

–NPSF3000
20年4月18日,0:32

如果您以这种方式进行设置。在不使用内部计费的公司中考虑这种情况的情况比较少见,但是内部客户离运营商足够远,而无需考虑成本

–user1937198
20年4月18日在1:30

它确实取决于确切的定价结构和机制。我对AWS更加熟悉,并且我当然知道有很多方法可以让您像那里的S3这样的次级账单。

–user1937198
20-4-18的1:37

次要问题:我不会将滥用DB的所有人称为恶意或不称职的人。分离前端和后端开发人员的部分原因是,前端无需掌握SQL或记住(大部分时间)对哪些字段建立了索引。将密钥交给数据库,然后该窗口就会消失。

– Ruther Rendommeleigh
20-4-18在8:59



#5 楼

在某些情况下,这可能是一种合理的方法:


客户获得只读访问权限。
他们获得对整个数据库的读取访问权限:这是准公共数据您所有的客户,或者仅包含他们自己的数据。特别是,它不得包含用户PII或受监管控制的数据。
您不介意他们随意阅读或复制内容。例如,如果它泄漏并完全公开,那就太烦人了。
他们不访问实时生产系统,而是访问后写镜像或数据仓库。
考虑并解决了敏感或特定于客户的数据泄漏到仓库中的风险。
该系统在技术上与您的实际生产系统隔离。我可能会考虑使用您的数据镜像创建Google BigQuery服务,并授予访问权限。
您有一种很好的方法来管理访问权限授予,包括撤销,滥用检测以及让客户管理授予他们的内部访问权限。同样,将其外包给BQ的IAM之类的IaaS提供者可能要比自己提出来容易得多。
您导出的模式足够稳定,或者您的客户足够宽容,因此更改模式和中断查询不是什么大问题。

这些条件并不完全是黑白色,但是直接访问包含许多用户信息的实时数据库,其风险正以其他答案描述的方式越来越高。

一个可能合理的假设场景是:您有一个待售物品的复杂零件目录。关于您拥有哪些零件以及它们的价格是什么的信息在商业上并不敏感,您也不必担心人们会保留这些零件的副本。而且它比简单的清单还要复杂:也许在定价方面存在复杂的关系,或者哪些部分协同工作。

如果所有这些条件都适用,那么出发点就是提供数据下载作为CSV或JSON。如果您不愿意这样做,那么授予SQL访问权限也可能不合适。但是,在某些情况下,授予BQ访问权限比提供下载要好:数据非常大(TB)?用户查询读取的数据相对较少。
数据经常导出,因此,批量下载将很难保持最新。
您想提供以下示例的固定示例有趣的查询并控制查询引擎。
您的客户有足够的技术来编写SQL,但又不想麻烦地运行自己的导入系统和数据库。
架构经常更改足以使导入自动化会中断,但不会中断查询。


这种模式的一个很好的例子是来自BigQuery上GitHub的3TB数据库。尽管所有这些信息都可以通过GitHub API获得,但是某些查询在SQL中将变得更加容易或快捷。其他数据集包括Google上的政治广告以及旧金山的电影地点。

评论


好答案。它描述了许多条件,必须满足所有条件,并且如果所有条件都满足,可以想象允许外部参与者相对直接地访问数据库(尽管可能存在更好的选择,例如GraphQL)。在所有其他情况下,这不是一个好主意。

–托马斯W
20-4-19在22:07



“客户希望对易于用SQL表示的数据进行复杂的操作,并且他们知道如何编写SQL。”这是我的第一要点-除非您的用户是高级SQL用户,否则这将无法工作-如果是,那么他们为您支付的费用是多少?

–龙
20年4月20日在16:20

@Dragonel我知道如何编写SQL,但我向很多公司支付了很多费用,它们是用于访问精心挑选的数据,或者是辅助数据的商品和服务。

–池
20-04-21在4:17

#6 楼

这是贝叶斯的答案...

作为一个行业,我们共同拥有大约三十年的设计面向用户的3层应用程序的经验,并且积累了丰富的知识对。某些其他答案表明,偏离这种模式并不一定是错误的,但是您将处于人烟稀少的地区,犯错误的风险更大。

评论


因此,这个问题!我并不是假设我比其他任何人都聪明,但是我想弄清楚为什么这不是解决问题的可行方法。

–莫里茨·弗里德里希(Moritz Friedrich)
20年4月18日在10:35

当您说“三层”时,您的意思是什么?我知道这是一个通用术语,但是人们使用的方式有所不同。

–paj28
20年4月18日在11:10

我假设1.客户端2.服务器3.数据库

–陆even
20-4-19的8:17

不同意。工业到​​达了学说。没有精英。信贷泡沫从根本上推动了行业发展。某些行业的Web开发人员与安全关键型行业的开发人员之间的文化差异非常大,例如控制系统,飞行,太空,军事,核能等。3层架构没有任何好处。只有武断的学说。

–坦率
20-04-19在20:45

#7 楼

有时会完成。 Esp。如果没有更好的选择,并且处于(受控的)受控环境中。成功率很低。


RDBMS在安全性方面远远落后于HTTP服务器。他们在开发和优化时考虑了不同的目标。他们的一般用例所面临的环境比典型的HTTP服务器友好得多。甚至无意中将侦听的DB端口暴露给Internet也被认为是安全性故障。
行级访问控制是一回事,但是它很少适合数据库的业务逻辑,并且数据库的规范化程度越高,并且您的许可系统越复杂,它就越不适合。互操作性:考虑到数据库访问协议及其相应驱动程序的深层混乱,您宁愿不将用户限制在某些开发堆栈或平台上。每个人都有HTTP或SOAP客户端可用,您选择的SQL Server客户端-您确定吗?您最好考虑更改数据库软件。从Oracle迁移到MySQL还是将过期从PostgreSQL 9.2升级到12?使用HTTP接口,您甚至不需要通知客户端就可以做到这一点。一些停机时间和一些错误以后就可以完成。
可用于HTTP的安全和网络管理工具(防火墙,代理,负载平衡器等)可用并且种类繁多。祝您找到了解TDS协议的入侵检测系统好运。


#8 楼

tl; dr:不要将您的DBMS暴露给公共网络,因为网络蠕虫喜欢攻击面很大。他们有反对我们的一切优势:他们很聪明,有很高的动力,他们只需要在我们的系统中找到一个漏洞来伪造我们。

我们正在捍卫我们的系统。我们必须塞住所有孔。一个好的出发点是限制孔的数量。

Web服务器是漏洞。在限制暴露于公共网络的Web服务器的攻击面方面,已经完成并正在进行大量的工作。当网络蠕虫提出一些新的Web服务器漏洞时,供应商通常会迅速推出补丁。而且,这些补丁对于我们迅速应用并不困难。

公开的DBMS也是一个漏洞。当然,其中一些具有出色的列,行,视图和表粒度访问控制。因此,从理论上讲,有可能在保持安全性的同时允许公共网络访问。

但是,如果网络蠕虫对DBMS进行某种形式的攻击,会发生什么?


DBMS服务器比Web服务器更为复杂,因此在缓冲区溢出,特权提升和其他攻击方面具有更大的潜力。功能的每一点都是潜在的攻击媒介。
由于大多数DBMS位于防火墙之后,因此发现的DBMS漏洞(比Web服务器漏洞)更少。
如果网络蠕虫侵入了您的DBMS,则它们已经对您的数据和应用程序进行了伪装。
确实很难在DBMS服务器上应用补丁来填补漏洞。
此外,如果将DBMS公开到公共网络,则安全审核员将不喜欢它。一点也不。而且出于充分的原因。
请不要这样做。

#9 楼


由于似乎没有人这样做,所以肯定存在我忽略的安全风险。
数据库级别,可能会产生严重后果。


为什么我们不能为客户提供公共SQL访问?
可能出什么问题?


您正在为客户的系统造成不必要的麻烦:客户必须了解您的数据库架构,还是只需要一部分数据库? />
这就是为什么从一年级开始,我们倾向于编写应用程序和API端点来抽象化数据库的结构。

#10 楼

实际上,类似类似Hasura的程序也可以完成类似的工作,该程序通过GraphQL接口使用PostgreSQL的权限系统对行级和列级权限公开数据库。客户端无法获得SQL查询的全部功能,但可以通过GraphQL查询获得子集。这样一来,查询就可以获取数据的子集(而不是每一列),以及联接和某种级别的过滤。没有充分发挥SQL的全部功能,这意味着您无法创建对服务器发起DOS攻击的查询。每个查询都转换为一个SQL查询,同时限制对可能会使服务器运行速度减慢的功能的访问。

对于迁移的担忧,您肯定能够通过迁移数据库来更新API。如果不需要,Hasura允许您使用自定义SQL视图将实际表转换为面向公众的视图,因此您可以更改内部表示形式而不会影响API。此外,您始终可以将Hasura换成其他任何只公开相同API的服务器,因此您不会被锁定。 WebSockets接口,以避免每次都重新连接。

评论


真的很有趣,我将为自己的一些项目研究Hasura。

–paj28
20-4-18在11:10



GraphQL是一个极好的选择,它可以在A)您要公开的内容与它的“逻辑模型”之间以及B)您的实际后端之间提供一个中介层。

–托马斯W
20-04-19在22:09

当我们不仅谈论SQL时,我想知道没有人提到FaunaDB或Firebase确实可以解决问题。

–Mišo
20年5月7日在20:29

@Mišo,除了我们在谈论SQL。 GraphQL可以提供基于SQL的抽象,但是某个地方仍然有一个SQL数据库。对于我来说,拥有一个甚至无法托管自己的数据库似乎很奇怪。

–lights0123
20年5月7日在20:33

@ lights0123,您可以通过SQL添加任何抽象。甚至有项目postgrest.org提供REST API。但就我个人而言,只要它提供查询语言(例如SQL,GraphQL(fauna.com),REST,...(firebase.google.com/产品/实时数据库)

–Mišo
20年5月8日在6:02



#11 楼

您问一个问题


为什么我不能让客户直接连接到我的数据库?


答案真的取决于您是谁在这种情况下是指客户。互联网上随机的人?正如大多数其他答复所言,这是一个坏主意,并且给出了许多充分的理由。但是,如果您的客户是值得信赖的业务合作伙伴,例如B2B,并且您的站点之间甚至还有联合的SSO解决方案之间都有VPN连接,那么这并不是一个好主意。这将是一场噩梦,但是除非有充分的文档证明,否则您将花费​​一整天的时间回答有关每个表中的数据的问题。


似乎没人这样做


您可能会感到惊讶。

评论


我同意您的看法,即作者未能定义他们的客户。要增加答案,您需要系统的直观程度可能是要考虑的因素。

–使用者
20年5月8日在17:07

#12 楼

即使在我所见过的最先进的RDBMS中,也无法获得足够好的安全性。除了最琐碎的应用程序以外的所有业务规则都太复杂了。如果您不希望邪恶的黑客造成严重破坏,则需要编写自定义代码,以特定的方式限制其功能。现在,您可以将其全部放入存储过程中,并且只允许您的客户端调用这些存储过程...,但是您又回到了开始的位置-在基础数据库之上仍然有一个自定义应用程序。而且,存储过程语言通常比通用编程语言(PHP / C#/ Java / Javascript / Ruby / Python / etc)笨拙且难以使用

评论


究竟。对于应用程序语言(Java,C#,Node JS),软件工程工具(IDE,调试器,框架,库,错误处理,日志记录,性能和概要分析)至少比存储过程/嵌入式数据库代码好两个数量级。 。

–托马斯W
20-04-19在22:12

#13 楼

如果您看一下Elasticsearch API的完成方式,那么您可能会发现与您的想法相似。
将客户端直接连接到Elasticsearch REST API就是这样。
(我并不是在倡导Elasticsearch。我只是发现这是您想法的一个很好的现实示例)

#14 楼

第三个要点确实是您的第一个要点,因为这是不允许直接访问的最重要原因。细粒度,所以我认为应该不存在任何明显的安全问题这么长时间以来一直是一件事情,没有行级安全性,您的方案就没有安全性。 MySQL甚至还没有行级安全性。

行级安全性并没有解决您的安全性和设计问题,这只是必要的第一步。基本上,没有什么比安全性问题更重要的了。

这是可以预期的。我将描述一个包含50到500个表的数据库较为复杂。即使人们100%诚实,我也不希望他们通过直接交互使用数据库。

我相信,在大多数组织中,如果可以通过应用程序完成某些事情,那么认为这样做比通过直接数据库访问更好,即使用户有能力和知识去做。它可以通过数据库进行访问。从一个至少可以假设所有用户即使不是同样熟练的人都值得信赖的组织扩展到更广泛的Internet,在这里您应该真正假设任何随机用户都是坏演员...

#15 楼

听起来好像您不太担心哪些客户端可以看到哪些数据行,或者您不必担心客户端需要更新而不仅仅是查询表。简单地直接或间接地向客户提供数据库的副本。想象一下,仅根据应用程序的复杂程度,将它们作为文件发送给SQLite克隆,要么在应用程序内,要么直接发送给他们。至少对于您的服务器而言,这避免了格式错误的查询带来的性能问题。完整。

#16 楼

只要您选择正确的数据库服务,这是可能的。现实情况是,很少有提供权限粒度和访问模型的混合体。无需尝试推广产品,但以今天为例,您可以使用“企业级”数据库系统完成类似的任务,例如


DB2
雪花
Oracle
> MSSQL

可能还有其他。

挑战在于这些系统的管理非常复杂。如果您
拥有团队,
可以支持并负担运营费用,并且
可以以这种方式出售数据产品,
>那么谁来阻止你?

通常阻止他们使用的是


更多的人才可以构建应用。应用程序可能也是他们首选的职业发展方式,并非罕见的DB配置开发人员
测试这些系统进行质量检查的方法不同于应用程序的方法。为此进行管理可能需要更多时间,或者遇到同样的人才挑战。
销售团队通常对技术不是很精明,但是解决方案工程师却很精明。大多数同行的解决方案工程师都不是数据库管理员。这增加了销售摩擦。人们买对他们有意义的东西。

轻踩一下。创新。做好计划。

#17 楼

安全性

应用程序服务器(Web服务器,容器等)应直接暴露给客户/不受信任的外部参与者,并为此进行更强大的安全性测试。相比之下,数据库服务器经常发现漏洞,如果直接暴露这些漏洞,很可能会受到利用。

应用程序逻辑和权限通常很重要。虽然数据库系统提供了一些有限的功能,但将它们集中在功能更强大的系统(应用程序逻辑)中通常可能更具凝聚力。对您的物理数据模型而言,会引起一个问题,即您在合同上/商业上有义务维护该完全相同的数据模型。这是非常不可取的,因为由于更改数据模型会破坏客户,因此无法维护/改善/重构数据模型。 (管理层会告诉您不要这样做。)如果您看不到客户如何使用它,这尤其糟糕。如果您为他们提供了原始的数据库连接,甚至您自己都无法解析/重写他们在做什么。

后端之间的可移植性也是一个问题。尽管数据库为您提供了安全性和存储的proc /脚本编制功能,但这些工具所提供的功能有限且工具差强人意,更糟糕的是它们是特定于供应商的。当出于性能/可伸缩性/成本的原因而要迁移到其他数据库时,您会发现自己陷于困境。物理实施。它的好处还在于,它通常可以为外部各方提供一个更简单,更清晰,更有用的模型。

更好的API结构/>
如前所述,定义一个清晰的逻辑模型通常更易于客户使用。
REST提供的功能使它可以从各种各样的客户端软件和工具中更广泛地使用,而不是要求客户端软件包括特定的数据库库,打开连接并运行SQL。
GraphQL这样的API标准可以提供您在整个逻辑模型中都非常好并且同时强大的通用图形访问和数据检索功能-即SQL的许多优点-同时提供了更好的权限和控制。

开发效率

软件工程工具-IDE,调试器,框架,库,错误处理,日志记录,性能和性能分析-对于应用程序语言(Java,C#..以及其他语言,例如Node JS,Rust,Go),可能比存储过程和嵌入式数据库代码好两个数量级。

鉴于终身维护成本是初始开发成本的4到10倍,即使是一个非常小的初始项目,例如将数据暴露给客户的7天,也可能会导致巨大的生命周期成本差异。在开发方面,我希望使用合理的应用程序语言工具和现代框架(Spring Boot,GraphQL或类似的工具)可使生产率提高3-4倍。在客户方面,我希望事情变得更容易使用,数据中断也要少得多(因为API能够保持稳定)。

那些声称不会有开发方面成本的人公开SQL可能会忽略尝试实现安全规则,尝试修补数据模型问题以及事后解决安全问题的成本。

编写自定义数据库连接代理以读取数据库有线协议,解析SQL查询并在SQL查询级别阻止安全性问题要花费多少钱?因为如果您允许原始SQL连接并且数据库规则不充分(我们几乎知道它们是),那么这就是您的安全性后备。帮自己和您的顾客一个忙。 GraphQL可能适合您,也可能不适合您,但它确实提供了SQL的许多优势,同时绕开了许多问题。

使用现代的应用程序语言和框架-我更喜欢Java(SpringBoot)或C#,但还可以使用NodeJS等其他选项。 (避免使用PHP)。

我建议:


插入GraphQL框架,构建逻辑模型,尝试GraphQL。为每个定义明确的视图提供一个REST API,在应用程序中实现权限逻辑,如果可能的话回答JSON -如果您的客户确实想要平面数据,则可以添加CSV选项。 br />

#18 楼

有优点也有缺点,但是如果您打算将数据库公开给客户端,则仅允许他们访问特定的架构,就可以使其成为小型攻击面。该架构将仅包含您将允许它们运行的​​存储过程。这将缓解SQL注入攻击,用户具有的授权取决于SQL授权。

如果希望不同的客户只能访问他们自己的记录,并且对同一客户组织中的不同人员具有不同的授权,则可以在越来越大的存储过程中进行所有这些操作。本质上,您是在存储过程中构建自己的API,并且如果要执行此操作,则最好在可维护性方面,在中间层中拥有自己的API层。如果您在性能和维护方面都具有复杂的业务逻辑,那么在中间层要比在存储过程中更好。程序,如果你想。无论是从功能角度还是从安全角度来看,您都可以使用较小的攻击面进行操作。但是,如果您有一个复杂的系统,并且了解其中涉及的内容,则大多数时候您将不想这么做。

#19 楼


为什么不能只让客户直接连接到我的数据库?为什么
不通过公开SQL端口而不让客户访问数据库,
完全跳过HTTP API?


您不能/不应该,因为数据库引擎提供的访问控制可能缺少适当控制客户端访问所需的粒度。

大多数数据库都已规范化,并且导致同一类型的所有对象存储在同一表中。甚至那些属于不同客户的数据库。

大多数(所有)数据库引擎权限系统都会一次授予或拒绝对整个表的访问,而不是逐条记录。而且您可能不希望一个客户看到其他所有客户的数据。

所以这就是为什么值得编写一个API处理程序来代表客户查询数据库并仅返回结果的原因任何给定的客户均有权接收。该API还可以实现数据库引擎无法实现的计费,费率调节,日志记录和其他便捷的业务功能。将客户需要的所有数据转储到某个表中,而您只授予他们访问该表的权限。但是,通常不为每个客户创建一个表,这违背了规范化。这会导致客户看到新数据的延迟,重复出现的IO高峰以重新生成客户可见的表,并使用大量的磁盘空间。 >

#20 楼

只要您不授予他们对数据的写访问权限,就不应允许他们修改或读取对他们不应该读取的数据的访问权限,这似乎是可以接受的。

许多系统将属于不同客户的数据放入共享表中,这显然是不合适的方法。

#21 楼

或者,您可以通过受信任的VPN建立连接。但是,就数据库服务器安全性而言,需要为属于数据库服务器上客户端数据库架构的用户配置更安全的权限和严格的访问权限。

但是不建议公共客户端使用此选项,通常仅用于内部拓扑。

#22 楼

我不会把它放在安全的角度,而是软件工程上。

为什么不让客户访问直接CRUD?

因为CRUD(创建,读取,更新,删除)基元是原子基元。
它们不实现业务逻辑。关系许可模型没有考虑到数据隔离。
假设安全性定义良好,这是CRUD无法正常工作的几个原因。
CRUD是原子的。对于企业来说太原子化了

借记卡和借记卡进行汇款。两个查询。您是否100%确定您的客户将以预期的顺序并在交易中运行所有查询?您的关系数据库不会强制执行牛顿约束,即“无法创建或销毁资金,而只能进行转移”。
REST API保证在事务中运行两个查询。

权限是有限的

关系权限未考虑数据语义和业务逻辑。如果您有权使用UPDATE(例如,出于讨论目的,您没有权限访问DELETE),则无法(轻松地)限制客户想要写入的值。
如果您更新UPDATE上的优惠券数量怎么办您的公司中实际上没有足够的优惠券时使用一个帐户吗?
REST API将在发出查询之前验证输入中的数据

权限不允许隔离

您通常会通过列值(例如TENANT_ID)来区分租户。 READ访问权限授予对每条信息的访问权限。
SQL权限允许将可用列限制为某个角色,而不是行。
REST API将为每个查询添加过滤器

审核和记录

通过直接CRUD访问,您将依靠客户发出INSERT INTO AUDIT_LOG。除了恶意,您确定所有人都会发出该查询吗?由于预算限制,我希望一些客户“忘记”实施该查询而忘记进行测试。
REST API将在每次调用时发布审核日志。众多用户。

相信我,我亲眼目睹了人类的灾难恢复...


#23 楼

当直接访问数据库时,您将失去对发出的CRUD语句类型的控制。恶意用户可以发出诸如from table_name中的delete之类的语句,并且所有数据都将丢失。最终用户现在最有可能知道数据库设计的地方。

评论


考虑一下,尽管他们没有特权删除表或从不属于其帐户的表中删除数据。例如,这就是MySQL本身所支持的。而且“友好”的观点有两点:Web开发人员可能更习惯于通过HTTP使用JSON,而如果有选择的话,数据分析人员则强烈偏爱SQL。

–莫里茨·弗里德里希(Moritz Friedrich)
20-4-17在13:47



我将接受Ariff的回答作为应用程序许可的明确示例。通常,应用程序是实现应用程序逻辑,应用程序权限控制和应用程序API的较好场所。从理论上讲,这些工具中的某些简单部分(并非全部)可以在数据库脚本中实现,这些工具的开发效率和有效性要低得多。应用程序是与数据库分开的一个词是有原因的。

–托马斯W
20-4-19在22:17



#24 楼

这就是为什么我们拥有诸如Business Objects之类的商业智能软件的原因:允许用户在不掌握SQL的情况下建立自己的查询,并且限制了他们所看到的内容。当然,可以基于每个用户设置权限。

为了给您一个想法,与我合作的一家公司提供了通过SAP Business Objects远程访问数据的功能。用户可以访问许多现成的报告,并且不能创建自己的报告(这是设计使然)。他们还每天(或每周)收到BO生成的一些Excel文件。他们对此非常满意,因为我们正在完成他们的工作,或者大部分工作。
一个重要标准是:您的客户是否需要实时数据。如果没有,则可以像CSV下载那样以受控方式提供数据。

乍一看,公开数据库似乎不是一个好主意。
我注意到您说的是客户,而不是开发人员,即实际上围绕您的系统进行开发并且出于正当理由需要远程访问的人员。我认为不应该授予非开发人员如此广泛的访问权限。其中之一正在受感染的计算机上工作(仍然有太多人运行破解软件或下载可疑的应用程序...)。从某种意义上说,无辜的用户可能比有经验的IT人员更危险,因为他们自己的安全性往往很弱。个人数据。您的公司可能受某些法规约束,例如GDPR,并可能因未能充分保护您的数据而被罚款。

您没有像黑客(或渗透测试人员)那样跳槽。细粒度的权限是最小的,但是您的安全范围超出了Mysql。您可以使用MySQL编写文件,显然不是在任意位置,但这取决于您的设置。如果Mysql配置错误(例如,以root用户身份运行)或您对某些文件夹具有过多权限,则存在一定的妥协空间。
select load_file('/etc/passwd') 


这里最明显的答案是拒绝FILE特权。但是您确定您已考虑所有可能的情况吗?如果事情出了问题并且您为此受了罪责,您是否愿意把工作放在一边? (我相信墨菲定律)。


因为似乎没有人这样做,所以肯定存在我忽略的安全风险。为什么我们不能向客户提供公共SQL访问权限?
可能出什么问题了? (请记住,这只是出于好奇而产生的思想实验)


最坏的情况:您的数据库服务器受到威胁,然后黑客使用该服务器作为通往企业其他网络的网关。
在现实世界中,每天都会发生这种情况:一台计算机遭到黑客攻击,工作站或服务器暴露在Internet上。它通常始于SQL注入或某些常见漏洞,或者仅仅是利用未打补丁的软件(Think Equifax)进行的利用。当黑客在计算机上立足时,他们就会进入您的网络,他们会发现什么?

评论


我认为这基本上是一个很好的答案,但我确实要挑战以下几点:1)对于CSV下载之类的东西,需要开发,而这正是OP试图避免的。 2)只有在技术决策不正确的情况下,这才动摇GDPR责任,而这正是所要提出的问题。 3)默认情况下,普通的MySQL用户没有FILE权限,因此必须错误地授予它,而不仅仅是忘记。 4)标准做法是将面向客户的系统放在DMZ中,以避免网络枢转。对不起,所有的蠢货,只想关注事实。

–paj28
20-4-17在14:59



我在很大程度上同意您的意见,但实际上我想比您更开箱即用:)这个问题故意保留得很广,因为我不想着重于实现。考虑提供对仅包含特定于客户的数据的分片只读副本的访问,例如,在其自己的DMZ中运行。甚至可能有一个只讲SQL子集并应用自己的限制的后端服务器。在这个问题空间中有很多可能性,我很好奇。提出此问题时,不会损害数据库服务器;)

–莫里茨·弗里德里希(Moritz Friedrich)
20-04-19在11:18