我第一次使用存储库模式开发ASP.NET MVC5项目。它有很多角色,每个角色都有很多用户。到目前为止,我已经创建了各种模型实体,添加,更新,删除方案都运行正常。在测试期间,我发现用户能够更新那些不属于他/她的实体。
我想限制用户访问,编辑,更新,删除属于用户本身的那些实体(db中的行),而不是其他实体。
我知道,我需要检查当前登录用户的if( answer=="Calculate" ||
answer == "calculate" ||
answer == "Road trip" ||
answer == "road trip"
)
{
// Whatever.
}
,但在userId
的情况下,我应该把它放在哪里。
我想到的两种方法是:将模型更改为在每个实体中具有Repository pattern with Entity Framework
属性,或者将每个实体与其父实体连接以获取相关的用户详细信息(获取{的完整实体链) {1}})。
实施此方法的首选方法是什么? 谢谢!
答案 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上使用)
有了这个,您可以在数据库级别过滤查询结果。