限制用户仅访问他/她的实体在Entity framework6存储库模式中

时间:2016-06-27 07:30:06

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

我第一次使用存储库模式开发ASP.NET MVC5项目。它有很多角色,每个角色都有很多用户。到目前为止,我已经创建了各种模型实体,添加,更新,删除方案都运行正常。在测试期间,我发现用户能够更新那些不属于他/她的实体。

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

我知道,我需要检查当前登录用户的if( answer=="Calculate" || answer == "calculate" || answer == "Road trip" || answer == "road trip" ) { // Whatever. } ,但在userId的情况下,我应该把它放在哪里。

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

实施此方法的首选方法是什么? 谢谢!

3 个答案:

答案 0 :(得分:1)

您可以从SaveChanges覆盖DbContext方法,并检查用户是否只更改自己的实体。此解决方案适用于使用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();

    }

答案 1 :(得分:0)

将每个实体与其父实体联系起来以获取相关的用户详细信息(获取userId的完整实体链)将是好的。创建一个具有共同属性的BaseEntity,如 UserId -

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

其他实体将继承基本实体,以便它们本身具有公共UserId属性 -

public class OtherEntity : BaseEntity {
    // properties
}

答案 2 :(得分:0)

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

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

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