繁体   English   中英

MVC存储库模式,如何进行安全修整?

[英]MVC repository pattern, how to security trim?

当前,我正在用MVC 4编写Web应用程序。我正在使用通用存储库模式。 它运作良好。 所以我有以下内容

public class AddressRepository : IAddressRepository
    {
        private AISDbContext context = new AISDbContext();

        public IQueryable<Address> GetAddresses()
        {
            return context.Address;
        }

    }

但是现在我需要添加一些可以进一步过滤数据的东西。 根据登录用户的角色,应该对这些数据进行更多过滤。

像这样

public IQueryable<Address> GetAddresses()
{
   return context.Address.where(x=>x.haspermissions = CURENTUSER.Role);
 }

现在,我总是可以添加另一个这样的函数,但是我想尝试一个通用的函数。 我想知道我是否可以仅使用第一部分代码并从另一个类继承而已,该类仅适用于安全性调整。 这样,我不必重写所有查询,只需告诉每个类从安全调整器继承即可。 希望有道理..

谢谢

更新的代码

public class AddressRepository : SecureRepositoryBase<Address>, IAddressRepository
    {
        private AISDbContext context = new AISDbContext();

        public IQueryable<Address> GetAll()
        {
            return base.RetrieveSecure(context.Address, 1);           
        }
}

 public abstract class SecureRepositoryBase<T> where T : ISecuredEntity
    {
        public IQueryable<T> RetrieveSecure(IQueryable<T> entities, int currentUser)
        {
            return entities.Where(e => e.InspectorId == currentUser);         
        }
    }

 public interface ISecuredEntity
    {
        int? InspectorId { get; set; }
    }

 public class Address: ISecuredEntity
    {
        public int COESNo { get; set; }
        public int Postcode { get; set; }
        public int AuditAuthNo { get; set; }
        public bool? SelectedForAudit { get; set; }
        public int? RECId { get; set; }
        public string CustomerName { get; set; }
        public string CustomerAddress { get; set; }
        public int? CustomerSuburbId { get; set; }
        public int? InspectorId { get; set; }
        public DateTime? AuditDate { get; set; }
        public int? AuditType { get; set; }
        public int? UploadType { get; set; }
        public string COESImage { get; set; }
        public DateTime CreatedDate { get; set; }
        public int? CreatedBy { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public int? ModifiedBy { get; set; }

        public virtual UserDetails Inspector { get; set; }
        public virtual Postcodes CustomerSuburb { get; set; }
        public virtual ResponsiblePerson RPerson { get; set; }
        public virtual UserProfile CreatedByUser { get; set; }
        public virtual UserProfile ModifiedByUser { get; set; }
    }

创建一个基类,将每个查询转换为检查权限的查询,并让您的存储库类从中继承。

像这样:

public interface ISecuredEntity
{
    IEnumerable<string> Permissions { get; }
}

public class Address : ISecuredEntity
{
    public IEnumerable<string> Permissions { get; set; }
}

public class AddressRepository : SecureRepositoryBase<Address>, IAddressRepository
{
    private AISDbContext context = new AISDbContext();

    public IQueryable<Address> GetAddresses()
    {
        return base.RetrieveSecure(context.Address, CURENTUSER);
    }
}

public abstract class SecureRepositoryBase<T>
    where T : ISecuredEntity
{
    public IQueryable<T> RetrieveSecure(IQueryable<T> entities, IUser currentUser)
    {
        return entities.Where(e => e.Permissions.Contains(currentUser.Role));
    }
}

您可能需要研究全局过滤器。 我将提供一个有关其工作原理的简短示例:

public class AISDbContext : DbContext
{
    public void ApplyFilters(IList<IFilter<AISDbContext>> filters)
    {
        foreach(var filter in filters)
        {
            filter.DbContext = this;
            filter.Apply();
        }
    }
}

public interface IFilter<T> where T : DbContext
{
    T DbContext {get; set;}
    void Apply();
}

public class AdminRoleFilter : IFilter<AISDbContext>
{
    public AISDbContext _dbContext {get; set;}
    public void Apply()
    {
        _dbContext.Address = new FilteredDbSet(_dbContext, d => d.haspermissions = "Admin");
    }
}

FilteredDbSet的详细信息确实很广泛,可以在这里找到。

那么你的执行DbContextAddressRepository是这样的:

var context = new AISDbContext();
context.ApplyFilters(new List<IFilter<AISDbContext>>()
    {
        new AdminRoleFilter()
    });

public List<Address> GetAddresses()
{
    return context.Address.ToList();
}

MVC存储库模式,如何进行安全修整?

存储库不应该进行访问控制/安全调整。 仅提供查询域对象的方法

在下面的代码中

function GetAddresses() as IQueryable(of Address)
function GetAddressesInspectedBy(Inspector as Inspector) as IQueryable(of Address)

方法GetAddresses将返回所有可用地址。

方法GetAddressesInspectedBy将返回具体检查员检查的所有地址。

这两种方法显然是不同的,并且在存储库中彼此共存。 两种方法都应该可用,但是调用哪种方法取决于存储库外部的业务逻辑/访问控制。

但是现在我需要添加一些可以进一步过滤数据的东西。 根据登录用户的角色,应该对这些数据进行更多过滤。

返回给用户的数据不应基于用户的角色! 相反,它应该基于用户的请求! 以及该请求是否可以执行取决于用户的角色。

例如,可以允许管理员角色用户请求以下每个请求

  1. 所有地址,
  2. 具体检查员的地址,
  3. 由他自己检查的地址。

三种请求类型中的每一种都将返回不同的结果,而与管理员角色无关!

虽然检查员角色用户只能被允许请求

  1. 仅由本人检查的地址。

应用程序接收请求,检查是否允许用户执行此请求,并调用与该请求相对应的存储库方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM