0

現在、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; }
    }
4

3 に答える 3

0

グローバル フィルターを調べることができます。それがどのように機能するかの簡単な例を含めています:

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は非常に広範で、ここで見つけることができます。

DbContext次に、 yourでの your の実装は次のようになりますAddressRepository

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

public List<Address> GetAddresses()
{
    return context.Address.ToList();
}
于 2013-06-14T13:27:39.443 に答える
0

各クエリをパーミッションがチェックされるものに変換する基本クラスを作成し、それをリポジトリ クラスに継承させます。

このようなもの:

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));
    }
}
于 2013-06-14T06:48:29.493 に答える
0

MVC リポジトリ パターン、セキュリティ トリムの方法は?

リポジトリは、アクセス制御/セキュリティ トリミングを処理する必要はありません。ドメイン オブジェクトを照会するメソッドを提供するだけです。

次のコードでは

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

このメソッドGetAddressesは、利用可能なすべてのアドレスを返します。

このメソッドGetAddressesInspectedByは、具象インスペクターによって検査されたすべてのアドレスを返します。

これら 2 つの方法は明確に区別され、リポジトリ内で共存します。どちらのメソッドも利用できるはずですが、どのメソッドを呼び出すかは、ビジネス ロジック/リポジトリ外のアクセス制御によって異なります。

しかし、データをさらにフィルタリングする何かを追加する必要があります。ログインしたユーザーの役割に基づいて、このデータをさらにフィルタリングする必要があります。

ユーザーに返されるデータは、ユーザーの役割に基づくべきではありません! 代わりに、ユーザーの要求に基づく必要があります。また、リクエストが実行されるかどうかは、ユーザーの役割によって異なります。

たとえば、管理者ロールのユーザーは、次のそれぞれを要求できます。

  1. すべてのアドレス、
  2. コンクリート検査官によるアドレス、
  3. 自分で調べた住所。

3 つのリクエスト タイプのそれぞれが、管理者の役割に関係なく、異なる結果を返します。

インスペクターロールのユーザーはリクエストのみを許可される場合がありますが、

  1. 自分だけが調べた住所。

アプリケーションはリクエストを受け取り、ユーザーがこのリクエストを実行できるかどうかを確認し、リクエストに対応するリポジトリ メソッドを呼び出します。

于 2016-10-12T09:14:16.203 に答える