【问题标题】:Restricting a user to access only his/her entities In Entity framework6 Repository pattern在Entity framework6 Repository模式中限制用户只能访问他/她的实体
【发布时间】:2016-06-27 07:30:06
【问题描述】:

我第一次使用 Repository 模式 开发一个 ASP.NET MVC5 项目。它有很多角色,每个角色都会有很多用户。到目前为止,我已经创建了各种模型实体,并且添加、更新、删除场景工作正常。在测试过程中,我发现用户能够更新那些不属于他/她的实体。

我想限制用户仅访问、编辑、更新、删除属于用户本身的那些实体(数据库中的行),而不是其他实体。

我知道,我需要在某处检查当前登录用户的userId,但如果是Repository pattern with Entity Framework,我应该把它放在哪里。

我想到的两种方法是:将模型更改为在每个实体中具有 userId 属性,或者将每个实体与其父实体连接起来以获取相关的用户详细信息(获取 userId 的完整实体链)。

实现这一点的首选方法是什么? 谢谢!

【问题讨论】:

  • 从头开始:您想要的商业目的是什么。换句话说,该功能需要如何工作?是否可以根据域模型层次结构中某处的用户/角色来限制数据访问?或者您是否希望每个实体都有一个相关的用户 (Id),从而对域模型的每个级别都有限制?
  • 这在角色基础上是不可能的,因为会有很多用户在同一角色中。只有userId 可以确定实体是否与他/她相关。
  • 为什么他们有可能一开始就做出这些不允许的修改?你的意思是他们甚至不应该查看其他用户的数据?

标签: c# entity-framework design-patterns asp.net-mvc-5 repository-pattern


【解决方案1】:

您可以覆盖 DbContext 中的 SaveChanges 方法并检查用户是否仅更改他/她自己的实体。此解决方案适用于任何使用 EntityFramework 的模式。

首先,您需要编写一个具有UserId 的接口,并且每个实体都必须实现它。

public interface IEntity   
{
    int UserId { get; set; }
}

public Blog : IEntity
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public int UserId { get; set; }
}

那么你需要覆盖SaveChanges。在这个方法中,如果一个实体被修改或删除,我们检查 UserId 是否匹配,否则抛出异常。 对于正在添加的实体,您可以分配当前的 UserId

public class ApplicationDbContext : DbContext
{
    public override int SaveChanges()
    {

        var ModifiedDeletedEntities = ChangeTracker.Entries()
              .Where(E => E.State == EntityState.Deleted ||
                          E.State == EntityState.Modified).ToList();
        foreach (IEntity entity in ModifiedDeletedEntities)
        {
            if (entity.UserId != GetCurrentUserId())
            {
                throw new Exception("Access Denied!");
            }
        }



        var AddedEntities = ChangeTracker.Entries()
               .Where(E => E.State == EntityState.Added).ToList();
        foreach (IEntity entity in AddedEntities)
        {
            entity.UserId = GetCurrentUserId();
        }



            return base.SaveChanges();

    }

【讨论】:

  • 这是一个很晚的警告。如果应用程序允许用户修改其他用户的数据,则用户可能无法再存储他们的有效部分更改。我认为重点应该是防止不允许的修改。
  • 这看起来不错,但在我的应用程序中,我有一些角色(例如,支持)可以编辑一些与用户相关的数据。我们甚至可以修改此解决方案以基于角色工作,以允许某些角色继续编辑其他用户数据并阻止某些角色这样做。
  • @vivek 是的,您可以根据需要修改此解决方案。您所要做的就是将 if 语句 if (entity.UserId != GetCurrentUserId()) 更改为您想要的任何条件。
【解决方案2】:

将每个实体与其父实体连接以获取相关的用户详细信息(获取 userId 的完整实体链)会很好。创建一个具有公共属性的 BaseEntity,例如 UserId -

public class BaseEntity {
    public int UserId {get;set;}
}

其他实体将继承基础实体,因此它们可以固有地拥有通用的 UserId 属性 -

public class OtherEntity : BaseEntity {
    // properties
}

【讨论】:

    【解决方案3】:

    另一个解决方案是使用新的 SQL Server 2016 功能:行级安全性。 (也可在 Azure 上使用)

    这样,您可以在数据库级别过滤查询结果。

    这是一个很好的起点:https://azure.microsoft.com/en-us/documentation/articles/web-sites-dotnet-entity-framework-row-level-security/

    【讨论】:

      猜你喜欢
      • 2019-12-21
      • 1970-01-01
      • 2012-07-13
      • 2023-04-11
      • 2020-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多