将数据验证完全委托给数据库引擎约束是一种好习惯吗?
验证来自应用程序的数据并不能防止来自另一个软件的无效插入(可能由另一个团队用另一种语言编写)。使用数据库约束可以减少需要担心无效输入数据的点。
如果你把验证同时放在数据库和应用程序中,维护变得很无聊,因为你必须为谁知道有多少应用程序更新代码,增加了人为错误的可能性。
从自由软件项目中查看代码,我只是看不到这样做太多。
将数据验证完全委托给数据库引擎约束是一种好习惯吗?
验证来自应用程序的数据并不能防止来自另一个软件的无效插入(可能由另一个团队用另一种语言编写)。使用数据库约束可以减少需要担心无效输入数据的点。
如果你把验证同时放在数据库和应用程序中,维护变得很无聊,因为你必须为谁知道有多少应用程序更新代码,增加了人为错误的可能性。
从自由软件项目中查看代码,我只是看不到这样做太多。
在输入时验证。在将其放入数据库之前再次验证。并具有数据库约束以防止错误输入。尽管如此,您可以打赌,不良数据仍会进入您的数据库,因此请在使用时再次验证它。
似乎每天都有一些网络应用程序被黑客入侵,因为他们使用 Javascript 以表单或更糟的方式进行了所有验证,人们找到了绕过它的方法。你必须提防这种情况。
偏执狂?我?没有,只是经历过。
在可能的情况下,最好在数据库中指定验证规则,并使用或编写一个框架,使这些规则冒泡到您的前端。ASP.NET 动态数据对此有所帮助,并且有一些商业库可以使其更加容易。
这既可以用于简单的输入验证(如数字或日期),也可以用于受外键约束的相关数据。
总而言之,这个想法是在一个地方(大多数时候是数据库)定义规则,并在其他层中有代码来执行这些规则。
将逻辑留给数据库的缺点是增加了特定服务器的负载。Web 和应用程序服务器相对容易向外扩展,但数据库需要特殊技术。作为一般规则,将尽可能多的计算逻辑放入应用程序层并保持与数据库的交互尽可能简单是一个好主意。
话虽如此,您的应用程序可能不需要担心如此严重的可伸缩性问题。如果您确定在可预见的将来数据库服务器负载不会成为问题,那么请继续对数据库进行约束。您是非常正确的,这通过将验证逻辑保留在中心位置来改善整个系统的组织性和简单性。
除了带有输入的 SQL 注入之外,还有其他问题。每当接受用户输入时,您都应该采取最防御的姿态。例如,用户可能能够将指向图像的链接输入到文本框中,这实际上是一个运行令人讨厌的 PHP 脚本。
如果您的应用程序设计得很好,您就不必费力地检查所有输入。例如,您可以使用为您处理大部分工作的 Forms API,以及执行相同操作的数据库层。
这是基本检查漏洞的好资源:
当数据到达您的数据库以为您的用户和应用程序提供有意义的验证时,为时已晚。您不希望您的数据库进行所有验证,因为这会减慢速度,并且数据库不能清楚地表达逻辑。同样,随着您的成长,您将编写更多应用程序级别的事务来补充您的数据库事务。
我会说这可能是一种不好的做法,具体取决于查询失败时会发生什么。例如,如果您的数据库可能会抛出由应用程序智能处理的错误,那么您可能会没事。
另一方面,如果您没有在您的应用程序中进行任何验证,您可能没有任何不良数据,但您可能会让用户认为他们输入了未保存的内容。
在不影响其他目标的情况下,在数据库端实施尽可能多的数据验证。例如,如果速度是一个问题,您可能需要考虑不使用外键等。此外,某些数据验证只能在应用程序端执行,例如,确保电子邮件地址具有有效域。
从数据库进行数据验证的另一个缺点是,您通常不会在每种情况下都以相同的方式进行验证。事实上,它通常取决于应用程序逻辑(用户角色),有时您可能希望完全绕过验证(cron 作业和维护脚本)。
我发现在应用程序中而不是在数据库中进行验证效果很好。当然,所有的交互都需要通过你的应用程序。如果您有其他应用程序可以处理您的数据,那么您的应用程序将需要支持某种 API(希望是 REST)。
我认为没有一个正确的答案,这取决于您的使用情况。
如果您将拥有一个使用率非常高的系统,并且数据库性能可能会成为瓶颈,那么您可能希望将验证的责任转移到前端,这样更容易与多台服务器一起扩展。
如果您有多个应用程序与数据库交互,那么您可能不想跨多个应用程序复制和维护验证规则,那么数据库可能是更好的地方。
您可能想要一个更流畅的输入屏幕,它不仅会在用户尝试保存记录时向用户发出验证警告,也许您希望在输入数据并且失去焦点后验证字段;甚至在用户键入时,在验证失败/通过时更改字体颜色。
与约束相关的还有可疑数据的警告。在我的应用程序中,我在数据库中有严格的限制(例如,某人无法在出生日期之前开始工作),但随后在前端对可能正确但可疑的数据发出警告(例如八年-老开始工作)。