【问题标题】:What, if any, design patterns are useful in implementing user based, record level permissions?如果有的话,什么设计模式在实现基于用户的记录级权限方面有用?
【发布时间】:2012-06-01 18:01:00
【问题描述】:

我正在使用 ASP.NET MVC 和使用 Repository 模式进行数据访问的实体框架来实现 Web 应用程序。此应用程序将有几个不相关的用户创建对象。每个用户都应该只能访问他们自己的对象。

是否有任何模式或内置 EF 功能提供一种方法来确保用户只能访问自己的记录?

我目前正在考虑向所有私有域对象添加一个 owner 字段,并实现一个对 DB 的所有查询都必须通过的类。此类将确定被查询的域对象是否是私有的。如果是这样,这个类将在 owner 上附加一个过滤器到查询中。这听起来合理吗?

【问题讨论】:

  • 问题是,用户关联通常被认为是数据,而不是数据。您可以将数据放在一起,但如何区分所有用户都需要访问的表和仅包含用户特定数据的表?如果您需要这样的机制,通常需要自定义构建。
  • 我正在考虑让那些私有的域对象实现一个 IPrivateData 接口,该接口还定义了 OwnerId 字段。如果域对象没有实现该接口,则它是公共的。
  • 这很有道理;但我认为您不会为此找到模式,因为它似乎是针对特定业务案例的。

标签: asp.net-mvc entity-framework design-patterns


【解决方案1】:

您问题的第二部分与Repository Pattern 的描述非常接近。这种方法可用于通过强制插入用户特定的过滤器来解决逐条记录的访问问题。

这种方法将您的客户端业务逻辑与基于行的安全性实现分离:如果您以后决定更改实现逐条记录访问的方式,您只需修改所有内容是您的存储库实现。客户端甚至不需要重新编译。

EF 将所有业务实体的存储库定义为部分类。您可以在其上添加一个接口(在单独的文件中),并使用 EF 生成的方法实现存储库的方法:

IMyRepository {
    IQueryable<ClientOrder> Orders;
    IQueryable<ServiceIssue> Issues;
}

// The other part of MyRepository is EF-generated.
// Assume that EF provides properties these properties:
// - ObjectSet<ClientOrder> AllOrders 
// - ObjectSet<ServiceIssue> AllIssues 
public partial SecureRepository : IMyRepository {
    private readonly Guid userId;
    public SecureRepository(Guid userId) : this() {
        this.userId = userId;
    }
    public IQueryable<ClientOrder> Orders {
        get {
            return AllOrders.Where(ord => ord.UserId == userId);
        }
    }
    public IQueryable<ServiceIssue> Issues {
        get {
            return AllIssues.Where(csi => csi.UserId == userId);
        }
    }
}

您可以添加写入方法,在将订单和问题保存到数据库之前设置UserId

【讨论】:

  • 可以并且应该将逐个记录的访问逻辑与存储库分离吗?让每个单独的存储库关注逐个记录的访问是否合理,或者某些第三方可以为所有存储库管理此操作?
  • @tQuarella 我添加了一个过于简化的代码示例,说明如何使用 EF 实现它。如果业务代码与IMyRepository交互,则数据被预过滤的事实对业务逻辑是隐藏的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多