实体框架每个用户的行级安全性

时间:2012-05-26 22:45:44

标签: c# entity-framework security dry

我正在使用Entity Framework和SQL Server 2008作为数据存储的ASP.Net MVC3网站。此外,我正在使用Repository模式将所有数据访问代码集中在一个区域中。

在我的应用程序中,我有很多用户,每个用户都可以有很多项目。用户应该只能访问自己的项目。 目前我有这段代码:

    public IQueryable<Project> All
    {
        get { 
            return context.Projects
                .Where(p => p.Owner.ID == Util.GetCurrentUserID())
                .Select(p=>p); 
        }
    }

    public Project Find(System.Guid id)
    {
        return context.Projects
                .Where(p => p.Owner.ID == Util.GetCurrentUserID())
                .FirstOrDefault();
    }

如果您发现.Where(p => p.Owner.ID == Util.GetCurrentUserID())重复。而且我还有其他一些地方,这些确切的条件都散落在其中。

DbContext中是否有一种方法可以将此条件自动附加到任何进入Projects表的查询中?

类似的东西:

public class MyContext : DbContext
{
    public DbSet<Project> Projects
         .Where(p => p.Owner.ID == Util.GetCurrentUserID()) { get; set; }
}

OR

public class MyContext : DbContext
{
    public DbSet<Project> Projects { get {
           // Insert a cast from IQuerieable to DBSet below
       return Projects
              .Where(p => p.Owner.ID == Util.GetCurrentUserID())
              .Select(p => p);
    } 
    set; }
}

UPD 在撰写问题时,意识到最后一个版本可以正常工作 - 需要尝试一下。仍然希望听到代码优化的其他选项,并使其更加干燥。

提前致谢!!

1 个答案:

答案 0 :(得分:4)

您始终可以编写名为“WhereProject”的扩展方法。然后在将条件附加到谓词后,在扩展方法中调用标准的“Where”方法。

public static IEnumerable<TSource> WhereProject<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) where TSource: Project
{
     return source.Where(p=> p.Owner.ID == Util.GetCurrentUserID() && predicate);
}

如果需要,可以跳过谓词,或者在默认值的参数列表中将其设置为null,如果不想使用谓词,则可以相应地执行操作。


这可能是你想要的,很简单:

public static IEnumerable<TSource> WhereProject<TSource>(this IEnumerable<TSource> source) where TSource: Project
{
     return source.Where(p=> p.Owner.ID == Util.GetCurrentUserID());
}

修改 这些解决方案对我来说听起来不对。我认为您希望将行数据保持在一个更高的级别,在我的情况下,它将是服务层。在服务类中考虑一个方法,如下所示:

public List<Project> GetUserProjects(User user)
{
    return repo.All().Where(p => p.Owner.ID == Util.GetCurrentUserID()).ToList();
}

这样,从方法名称来看,你在做什么就很清楚了。包含特定逻辑的存储库不是责任。它只能处理您的数据访问。