【问题标题】:Which parameter validations should be done in each layer?每一层应该进行哪些参数验证?
【发布时间】:2011-02-04 14:17:41
【问题描述】:

不久前我曾就这个主题提出过类似的问题,并得到了一些很好的反馈,但我仍然对如何继续存在一些疑问。

这里是场景...

应用允许用户发布和删除他们关于视频的 cmets。

当用户发表评论时,UI 层传递评论字符串和 userId (guid),删除时将 commentId (int) 和 userId (guid) 传递给 BLL,然后传递给 DAL。

在 UI 层,我假设我需要进行全面验证,因此我使用客户端(如果适用)和服务器端验证确保以下内容:

  • userId 实际上是一个 guid
  • userId存在于用户数据库中(通过调用BLL方法)
  • userId 是与commentId 关联的一个(用于删除)(通过调用BLL 方法)
  • 评论不为空
  • 评论不超过最大长度
  • commentId > 0
  • commentId 存在于数据库中(通过调用 BLL 方法)
  • videoId > 0
  • 数据库中存在videoId(通过调用BLL方法)

在所有这些验证发生后,我将调用 BLL 方法

保存(字符串注释,int videoId,字符串 userId) 或者 删除(int commentId, string userId)

由于 BLL 也可以用作 Web 服务或其他页面/应用程序,我知道我也需要在 BLL 中进行验证。根据我了解到的情况,我认为我需要重做我在 UI 层中所做的所有相同验证:

  • userId 实际上是一个 guid
  • userId存在于用户数据库中(通过调用BLL方法)
  • userId 是与commentId 关联的一个(用于删除)(通过调用BLL 方法)
  • 评论不为空
  • 评论不超过最大长度
  • commentId > 0
  • commentId 存在于数据库中(通过调用 BLL 方法)
  • videoId > 0
  • 数据库中存在videoId(通过调用BLL方法)

这是正确的吗?除非必须,否则我讨厌进行额外的数据库调用!

现在我需要调用相关的 DAL 调用来实际进行数据库更改。我需要在 DAL 中再次执行上述哪些验证?

这个应用程序没有被出售或任何东西,但我想了解处理验证的最佳方法,而不会因为我可能需要或可能不需要的额外数据库调用而降低性能。

【问题讨论】:

  • 我希望知道哪些项目应该在哪一层进行验证。

标签: c# asp.net parameters validation


【解决方案1】:

我在 UI 层只对可能是无辜的用户错误的事情进行验证。这里的验证纯粹是为了可用性。从您的列表中,那将是

  • 评论不为空
  • 评论不超过最大长度

幸运的是,这些不需要数据库调用。

在后端,您需要验证列表中的所有内容。只有这样才能真正确保确保有效性、安全性、完整性等。

如果某些东西通过了 UI 层验证但没有通过后端验证,那么就发生了非常非常错误的事情 - 可能是恶意用户或代码中的错误。如果这是您的代码中的错误,那么向用户显示验证消息对他们并没有真正的帮助。如果是恶意用户,验证消息实际上是有害的,因为它们使坏人更容易确定您进行了哪些验证检查并找到漏洞。当后端验证失败时,您的应用应该只向用户提供一般错误消息。

【讨论】:

  • 所以你认为我应该在业务层和数据层进行所有这些相同的验证?
  • 每一层都应该验证以下几点:1) 它是最适合这样做的层,或者 2) 可能被该层的无辜消费者攻击并保证友好的错误消息。对于#1,您的业务层是验证业务规则的好地方......它最适合于此,因为它是定义业务规则的地方。您不想复制更高级别的所有内容,而较低级别的数据层应该对业务规则一无所知。对于#2,这实际上取决于还有谁在使用您的 BLL - 使用它来决定为此付出多少努力。
  • 对于那些验证注释不为空且不超过最大长度...应该是位于我的域对象/BLL 中被调用的方法还是直接在 UI/代码隐藏中进行验证?
  • @Developr - 永远不要只在 UI 层进行验证。恶意用户或行为不佳的 BLL 使用者不会受到 UI 层验证的约束。
【解决方案2】:

在我看来,您应该在每个级别验证您有能力验证的每个项目。冷战时期“信任但验证”的说法在这里适用。假设您有一个分层的方法,并且每一层都有可能在稍后的某个时间点在另一个项目中被重用,假设未来的上层将以与原始层相同的方式进行验证,这是一个错误的假设。

显然,这可能会比业务逻辑添加更多的验证,甚至重复验证,但可能更安全。

如果您希望保存 DB 调用,那么我会说在最低级别执行它们,但只需确保您在较高级别的错误处理足够健壮,以处理各种冒泡的错误情况。

【讨论】:

    【解决方案3】:

    我不建议您在每个 chack 都有自己的数据库调用时进行大量额外检查。如何创建一个存储过程并将所有数据库检查放入其中。然后你可以调用“Class.IsDatabaseValid(string, string, Id, 不管)”。因此,“IsDatabaseValid”方法将成为 BLL 有效性检查的一部分,并且您在 sp 上有一个单独的 db 调用。

    【讨论】:

      【解决方案4】:

      我知道一个相当简单的答案,但是由于每一层都代表一个边界,因此您不能信任该层之外的任何代码,因此虽然您可能在 UI 中进行了验证,但您应该查看在业务层(域) 作为唯一真正的验证逻辑。

      参见 Expert C# 2008 Business Objects 的第 11 页,业务逻辑。

      【讨论】:

        猜你喜欢
        • 2013-04-29
        • 1970-01-01
        • 1970-01-01
        • 2023-03-21
        • 2019-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多