1

我正在寻找一些有关特定于客户端/服务器解决方案的体系结构建议。保护敏感实体数据

客户端是一个相当厚的客户端,主要是服务器保持持久性,并发性和基础设施问题。 服务器包含许多包含敏感信息和公共信息的实体。例如,假设实体是人,假定社会安全号码和姓名是敏感的,并且年龄是公开可见的。

启动客户端时,会向用户呈现多个实体,而不会泄露任何敏感信息。在任何时候,用户都可以选择登录并对服务器进行身份验证,但鉴于身份验证成功,用户可以访问敏感信息。

客户端正在托管一个域模型,并且我正在考虑将其实现为某种“延迟加载”,从而使第一个请求实例化实体,然后使用敏感数据刷新它们。还没有被披露时,他们的实体干将会抛出敏感信息出现异常,f.e:

class PersonImpl : PersonEntity 
{ 
    private bool undisclosed; 

    public override string SocialSecurityNumber { 
     get { 
      if (undisclosed) 
       throw new UndisclosedDataException(); 

      return base.SocialSecurityNumber; 
     } 
    } 
} 

另一种更友好的方式可能是具有指示值是未公开的值对象。

​​

有些担忧:

  • 如果什么,然后出来在用户登录时,敏感数据被加载,但必须再次披露。
  • 有人可能会争辩说,这种类型的功能属于域内,而不属于某些基础设施实现(即存储库实现)。
  • 按照一贯的特性较大数量的问题时有这种类型的功能杂波的代码

任何见解或讨论表示赞赏的危险!

回答

2

我认为这实际上是使用视图模型的一个很好的例子。由于它们包含的数据,您的担心似乎与实体的消费直接相关。与其将实体一直传递到用户界面,您可以将它们限制为仅在域内生存 - 即根本不会将实体传入或传出域,而大部分/所有活动都是通过命令/查询方式完成的在存储库上。然后存储库会返回一个视图模型而不是实体。

那么如何/为什么这适用?你实际上可以有两种不同的视图模型。一个用于身份验证,一个用于未经身份验证的用户。您公开验证视图模型中敏感数据的实际值,而不是未验证的值。您可以让它们从一个通用接口派生,然后针对接口而不是对象类型进行编码。对于未经身份验证的用户的具体实现,您可以填充不敏感的数据,让敏感的获取者执行您希望他们执行的操作。

上几个百分点的我意见

  • 我不是延迟加载的实体风扇。延迟加载是数据访问责任,并不是模型的一部分。对我而言,它是我在域中强烈避免的事情中的头等成员,以及分页和排序。至于如何将这些项目联系在一起,我宁愿通过ID指针松散地将对象耦合到其他实体。如果我想要/需要其中一个实体包含的数据,那么我可以加载它。这种方式有点像延迟加载,但我强制要求它在域模型本身中不会发生这种情况。
  • 我不喜欢在getter上抛出异常。另一方面,安装者很好。我是这样看的。实体应始终处于有效状态。吸气者不会影响实体的状态 - 设定者会。投入二传手是为了强化模型的完整性。使用两种视图模型方法可以让我将逻辑转移给演示者。所以,我基本上可以做一些事情,如“如果用户是非授权类型的,那么做,否则做别的事情”。因为你所指的最终将是数据如何呈现给用户,对模型不重要的情况,我认为它很合适。一般来说,我使用可为空的类型作为我的属性,它们可以为null,并且不会对getter执行任何操作,因为它通常不是其职责的一部分。相反,我使用角色来确定要使用的视图模型。

显而易见的缺点是,使用视图模型需要更多的编码,但它具有将表示和视图从域中解耦的显而易见的好处。它还将有助于单元/集成测试,您可以验证某个视图模型无法返回某种类型的数据。

但是,您可以使用与AutoMapper类似的东西(取决于您的平台)以帮助从实体填充视图模型。

0

我犯了一个错误发布的问题,而不创建一个OpenId,所以它看起来我必须在这里发表评论(?)。

首先,感谢您花时间回答 - 它肯定与数据的呈现方式有关,而不是模型的工作方式。不过,我觉得有必要澄清一些事情。 域模型/实体不会直接从UI中引用。我正在使用用于UI /业务模型分离的DM-V-VM模式的变体。对于一般的懒惰加载和存储库实现,我在基础结构层实现了一些实现,比如序列化,脏跟踪和延迟加载。

因此域层实体,如:

class Entity { 
    virtual string SocialSecurityNumber { get; } 
} 

,基础设施层增加了一些其他功能,以便能够随时更新和服务器恢复的entites:

class EntityImpl : Entity { 
    bool isDirty; 
    bool isLoaded; 
    // Provide the means to set value on deserialization 
    override string SocialSecurityNumber; 
} 

所以延迟加载行为将在基础设施层实施,域层从未见过。

我同意扔getter不会很好,但我的担心是关于匿名视图模型如何检索数据。到目前为止,为了检索实体列表,视图模型将持有对域存储库的引用,我应该有两个存储库,一个用于已认证(因此已公开)的实体,另一个用于未认证的用户 - 可能甚至包括两个不同的实体?