防止不良数据输入

时间:2020-03-06 14:19:33  来源:igfitidea点击:

将数据验证完全委派给数据库引擎约束是一种好习惯吗?

验证来自应用程序的数据不会阻止从另一软件(可能由另一团队用另一种语言编写)的无效插入。使用数据库约束可以减少需要担心输入数据无效的问题。

如果在数据库和应用程序中都进行验证,则维护变得很无聊,因为我们必须更新知道谁有多少应用程序的代码,从而增加了人为错误的可能性。

我只是看着免费软件项目中的代码而看不到这完成得太多。

解决方案

我想说这可能是一个坏习惯,具体取决于查询失败时发生的情况。例如,如果数据库可能抛出由应用程序智能处理的错误,那么我们可能会没事。

另一方面,如果我们不对应用程序进行任何验证,则可能没有任何不良数据,但是我们可能会让用户认为他们输入了无法保存的内容。

在输入时间进行验证。在将其放入数据库之前,请再次进行验证。并具有数据库约束以防止输入错误。而且尽管如此,我们仍然可以打赌,不良数据仍会进入数据库,因此在使用时再次进行验证。

似乎每天都有一些Web应用程序被黑客入侵,因为他们使用Javascript以某种形式或者更糟糕的方式进行了所有验证,人们发现了一种绕过它的方法。我们必须提防这一点。

偏执狂?我?不,只是经验丰富。

在数据库端实现尽可能多的数据验证,而不会影响其他目标。例如,如果速度是一个问题,我们可能要考虑不使用外键等。此外,某些数据验证只能在应用程序端执行,例如,确保电子邮件地址具有有效域。

将逻辑留给数据库的缺点是增加了该特定服务器上的负载。 Web和应用程序服务器相对容易向外扩展,但是数据库需要特殊的技术。通常,将尽可能多的计算逻辑放入应用程序层并保持与数据库的交互尽可能简单是一个好主意。

话虽如此,应用程序可能不必担心此类繁琐的可伸缩性问题。如果确定在可预​​见的将来数据库服务器负载不会成为问题,请继续对数据库施加约束。我们非常正确地认为,通过将验证逻辑放在中央位置,可以改善整个系统的组织性和简化性。

从数据库进行数据验证的另一个缺点是,在每种情况下,我们通常都不会以相同的方式进行验证。实际上,它通常取决于应用程序逻辑(用户角色),有时我们可能希望完全绕过验证(定时作业和维护脚本)。

最好尽可能在数据库中指定验证规则,并使用或者编写框架以使这些规则冒泡到前端。 ASP.NET动态数据对此提供了帮助,并且有一些商业库使其变得更加容易。

对于简单的输入验证(如数字或者日期)以及相关数据(如受外键约束的数据),都可以这样做。

总而言之,该想法是在一个位置(大多数时间是数据库)中定义规则,并在其他层中执行将执行这些规则的代码。

除了带有输入的SQL注入之外,还有其他一些问题。接受用户输入时,我们应尽可能采取最防御的态度。例如,用户也许能够在文本框中输入图像的链接,而文本框实际上是一个运行讨厌的PHP脚本。

如果我们设计良好的应用程序,则不必费力检查所有输入。例如,我们可以使用一个Forms API来完成大部分工作,而使用一个数据库层则可以完成很多工作。

这是基本检查漏洞的好资源:

http://ha.ckers.org/xss.html

到数据到达数据库以为用户和应用程序提供有意义的验证时,为时已晚。我们不希望数据库执行所有验证,因为这会使速度变慢,并且数据库无法清楚地表达逻辑。同样,随着成长,我们将编写更多的应用程序级别的事务来补充数据库事务。

我发现在应用程序而不是数据库中进行验证效果很好。当然,所有交互都需要通过应用程序。如果我们还有其他处理数据的应用程序,则应用程序将需要支持某种API(希望是REST)。

我认为没有一个正确的答案,这取决于使用。

如果我们将拥有一个使用率很高的系统,而数据库性能可能会成为瓶颈,那么我们可能希望将验证责任转移到前端,在前端可以轻松扩展多个服务器。

如果我们有多个应用程序与数据库交互,那么我们可能不想跨多个应用程序复制和维护验证规则,因此数据库可能是更好的选择。

我们可能需要一个闪烁的输入屏幕,它不仅在用户尝试保存记录时用验证警告击中用户,也许我们想在输入数据后失去焦点,从而验证字段;甚至当用户输入时,随着验证失败/通过,更改字体颜色。

与约束有关的还有可疑数据的警告。在我的应用程序中,我在数据库中有严格的约束条件(例如,某人不能在出生日期之前开始工作),但是在前端,则警告那些可能正确但可疑的数据(例如八年岁开始工作)。