Which parameter validations should be done in each layer?
我之前曾在这个问题上问过类似的问题,并获得了很好的反馈,但是我仍然对如何进行有疑问。
这是场景...
App允许用户发布和删除他们对视频的评论。
当用户发布评论时,UI层将评论字符串和userId(guid)传递给用户,当删除时,会将commentId(int)和userId(guid)传递给BLL,然后BLL传递给DAL。
在UI层,我假设我需要进行完全验证,因此我确保同时使用客户端(如果适用)和服务器端验证进行以下操作:
- userId实际上是一个向导
- userId存在于用户数据库中(通过调用BLL方法)
- userId是与commentId关联的对象(用于删除)(通过调用BLL方法)
- 评论不为空
- 评论不超过最大长度
- commentId为> 0
- commentId存在于数据库中(通过调用BLL方法)
- videoId> 0
- videoId存在于数据库中(通过调用BLL方法)
所有这些验证完成后,我将BLL方法称为
保存(字符串注释,int videoId,字符串userId)
或者
Delete(int commentId,字符串userId)
由于BLL也可以用作Web服务或用于其他页面/应用程序,因此我知道我也需要在BLL中进行验证。从我学到的知识来看,我认为我需要重做与UI层中相同的所有验证:
- userId实际上是一个向导
- userId存在于用户数据库中(通过调用BLL方法)
- userId是与commentId关联的对象(用于删除)(通过调用BLL方法)
- 评论不为空
- 评论不超过最大长度
- commentId为> 0
- commentId存在于数据库中(通过调用BLL方法)
- videoId> 0
- videoId存在于数据库中(通过调用BLL方法)
这是正确的吗?除非必须,否则我讨厌进行额外的数据库调用!
现在,我需要调用关联的DAL调用来实际进行数据库更改。我需要在DAL中再次执行上述哪些验证?
该应用程序没有出售或出售任何东西,但我想了解处理验证的最佳方法,而又不会因我可能需要或可能不需要的额外数据库调用而影响性能。
我仅在UI层中对可能是无辜的用户错误的内容进行验证。这里的验证纯粹是出于可用性的考虑。在您的列表中,该值为
- 评论不为空
- 评论不超过最大长度
幸运的是,这些不需要数据库调用。
在后端,您需要验证列表中的所有内容。这是真正确保确保有效性,安全性,完整性等的唯一方法。
如果某项通过UI层验证但未通过后端验证,则发生非常非常错误的事情-恶意用户或代码中的错误。如果这是您代码中的错误,向用户显示验证消息对他们并没有真正的帮助。如果是恶意用户,则验证消息实际上是有害的,因为它们使坏人更容易确定您执行的验证检查并发现漏洞。当后端验证失败时,您的应用应仅向用户显示一般错误消息。
在我看来,您应该在每个级别上验证您有能力验证的每个项目。冷战时代"信任但要核实"的说法在这里适用。假设您有一个很好的分层方法,并且每个层都有可能在另一个项目的以后某个点被重用,那么假设将来的上层将验证原始层的使用方式是一个错误的假设。 >
显然,与业务逻辑相比,它具有添加更多验证的潜力,甚至可以重复验证,但可能更安全。
如果您希望保存数据库调用,那么我想说是在最低级别上进行的,但是只要确保您在较高级别上的错误处理能力足够强大,就可以处理各种冒泡的错误情况。
我知道这是一个相当简单的答案,但是由于每个层都代表一个边界,因此您不能信任该层之外的任何代码,因此,尽管您可以在UI中进行验证,但应该查看在业务层中运行的逻辑(域)作为唯一的实际验证逻辑。
请参阅Expert C#2008业务对象的第11页,业务逻辑。
我不建议您对每个黑客都有自己的数据库调用进行大量额外的检查。如何创建存储过程并将所有数据库检查放入其中。然后,您可以调用" Class.IsDatabaseValid(字符串,字符串,Id等)"。因此," IsDatabaseValid"方法将成为BLL有效性检查的一部分,并且您在sp。
上只有一个数据库调用。