【问题标题】:Securing/omitting selected properties of a domain entity in NHibernate (subclass, projection, ?)保护/忽略 NHibernate 中域实体的选定属性(子类、投影、?)
【发布时间】:2010-09-07 17:27:26
【问题描述】:

考虑以下简化场景:

public class Person
{
    public string Name { get; set; }

    public int Age { get; set; }

    // restricted
    public string SocialSecurityNumber { get; set; }

    // restricted
    public string MothersMaidenName { get; set; }
}

因此,在应用程序中,许多用户可以查看Person 数据。部分用户可以查看全部;其他用户只能查看NameAge

让 UI 仅显示授权数据在客户端很容易,但我真的不想将该数据发送到客户端。

我试图通过创建FullPerson : BasicPerson 层次结构(每类层次结构表)来实现这一点。我使用了 StaffRepository 的两个实现来获得所需的类型,但是由于 NH 代理,必要的转换在运行时失败。当然,在 RDBMS 中,People 表中的任何给定行都可以表示FullPersonBasicPerson,并且给它们两个相同的鉴别器值也不起作用。

我考虑只映射FullPerson 并使用AliasToBean 结果转换器过滤到BasicPerson,但我理解这是一条单向街道,而我想要实体管理和延迟加载的全部好处(虽然上面的示例不包括集合)在会话中。

我的另一个想法是将所有受限制的字段包装到一个类中并将其添加为属性。我对这种方法的担忧有几个:

  1. 它破坏了我的域模型,
  2. 我必须将该属性声明为一个集合(始终为 1)才能使其延迟加载,并且
  3. 我什至不确定如何防止加载该惰性集合。

这一切都感觉不对劲。是否有已知的方法来达到预期的结果?

澄清:

这在仅限 Intranet 的桌面应用程序中;会话存在于客户端上。虽然我当然可以创建一个中间服务层,但我必须放弃延迟加载和更改跟踪,我真的很想保留这些。

【问题讨论】:

    标签: c# nhibernate domain-driven-design nhibernate-mapping smartclient


    【解决方案1】:

    首先,让我说,我不认为 N​​Hibernate 有责任处理安全性,以及基于相同的数据编辑。我认为您尝试将其放在数据访问层中会使它过于复杂。

    我会在服务或控制器中插入一个层,该层从客户端(不应该是存储库本身)接收此数据请求,并将根据用户权限执行数据编辑。因此,您将对数据库执行完整查询,然后根据用户权限,服务层将在通过服务连接返回该结果集之前清除结果集的字段。它不是绝对性能最高的解决方案,但比将所有数据发送到客户端并让客户端软件“审查”它更安全、更高效。服务器架构的 DB 和服务层之间的以太网连接可以处理比服务层和客户端之间的 Internet 连接更多的带宽,并且在远程客户端应用程序中,您通常几乎无法控制客户端如何处理数据;您可能正在与您的软件或类似软件的被黑副本交谈,这不会给用户安全性带来两次翻转。

    如果服务和数据库之间的网络带宽非常重要,或者如果大量信息受到限制,Linq2NH 应该足够智能,让您可以使用选择列表指定查询结果中应该或不应该包含的内容:

    if(!user.CanSeeRestrictedFields)
       var results = from p as Repository.AsQueryable<Person>()
       //rest of Linq statement
       select new Person { 
             Name = p.Name,
             Age = p.Age
          };
    else
       var results = from p as Repository.AsQueryable<Person>()
       //rest of Linq statement
       select new Person { 
             Name = p.Name,
             Age = p.Age,
             SocialSecurityNumber = p.SocialSecurityNumber,
             MothersMaidenName = p.MothersMaidenName
          };
    

    我不知道 Linq2NH 是否足够聪明,可以将条件运算符解析为 SQL;我对此表示怀疑,但有可能,您可以根据用户是否有权查看 SSN 和 MMN 字段在初始化程序中指定条件运算符,从而允许您组合这两个查询。

    【讨论】:

      【解决方案2】:

      我将不理会您的域模型,而是使用Automapper 根据当前用户的安全级别(或您用来确定对特定属性的访问权限的任何标准)映射到特定的 DTO。这应该在位于 UI 和存储库之间的某种服务层中完成。

      编辑:

      根据您保持延迟加载和更改跟踪的要求,也许使用proxy pattern 包装您的域对象是一个可行的选择?您可以将原始域模型包装在对每个给定属性执行安全检查的代理中。我相信CSLA.NET 使用这样的方法来实现字段级安全性,因此可能值得浏览源代码以获取一些灵感。您或许可以更进一步,使用由您的代理实现的接口,这些接口只公开用户有权访问的属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-10
        • 1970-01-01
        • 2017-04-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多