4

這是我的第一個問題在stackoverflow,所以請溫柔。我正在使用MVC4,Entity Framework和SimpleMembership寫入一個倉庫應用程序的客戶門戶。倉庫爲多家公司提供內容。每個公司都有分部和部門。用戶將擁有不同的公司,部門和部門信息。我正在尋找一個優雅的訪問控制解決方案。到目前爲止,我的模型是這樣的:實現公司,部門,部門MVC4用戶訪問控制與EF

public class UserProfile 
{ 
    UserProfile() 
    { 
     this.AccessControl = new HashSet<AccessControl>(); 
    } 

    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
    public Nullable<int> CompanyId { get; set; } 
    public virtual ICollection<AccessControl> { get; set; } 
    public virtual Company Company { get; set; } 
} 

public class AccessControl 
{ 
    public int AccessControlId { get; set; } 
    public int UserId { get; set; } 
    public int CompanyId { get; set; } 
    public Nullable<int> DivisionId { get; set; } 
    public Nullable<int> DepartmentId { get; set; } 
    public Boolean ReadAccess { get; set; } 
    public Boolean WriteAccess { get; set; } 

    // other properties for access control 

    public virtual UserProfile UserProfile { get; set; } 
    public virtual Company Company { get; set; } 
    public virtual Division Division { get; set; } 
    public virtual Department Department { get; set; } 
} 

public class Content 
{ 
    public int ContentId { get; set; } 
    public int CompanyId { get; set; } 
    public int DivisionId { get; set; } 
    public int DepartmentId { get; set; } 

    // Various other properties 

    public virtual Company Company { get; set; } 
    public virtual Division Division { get; set; } 
    public virtual Department { get; set; } 
} 

我的想法是,一個空司意味着所有部門和空指部各部門。我的問題是:

  1. 是編寫庫方法來檢索內容對象的列表基於它們的訪問控制列表上的用戶以及在CRUD觀點填充分工和部門選擇列表優雅的方式?
  2. 有沒有更好的方法來建立此訪問控制列表?
+1

你是否已經有了一個「不雅」的解決方案,可以改善?對於公司,部門和部門而言,可能出現的'空'案件很難解決問題,甚至更多的是一種「優雅」的解決方案,不會有冗長的案件延期序列。如果沒有'null'sa查詢可能是:'var query = from c in context.Contents join in a context.AccessControls on new {c.CompanyId,c.DivisionId,c.DepartmentId} equals new {a.CompanyId,a。 DivisionId,a.DepartmentId}其中a.UserProfile.UserId == givenUserId選擇c;'但我未能擴展這個以覆蓋'null's。 – Slauma 2013-03-02 14:47:25

+0

關於您的部門/部門選擇清單,您能否詳細說明您對CRUD視圖的設想? (即你想做什麼可以做一個視圖) – 2013-03-02 18:19:09

+0

謝謝你的答案。如果用戶A有兩個訪問控制對象。一個可以訪問分區1,會計和另一個可訪問分區1,財務部門,然後在創建,更新或刪除時選擇列表將爲分部提供分區1,爲部門選擇列表提供會計和財務部。如果用戶對所有部門(即部門爲NULL)和部門銷售部門都有一個訪問控制對象,則選擇清單將包含所有定義的部門,並且僅包含銷售部門。 – tomc 2013-03-02 23:27:44

回答

0

我不認爲這解決您的所有問題,但我認爲一個倉庫,看起來是這樣的:

public class accessRepository 
{ 
    accessContext context = new accessContext(); 

    public IQueryable<Content> GetAccessibleContentFor(int userId) 
    { 
     var up = context.UserProfiles.Single(u => u.UserId == userId); 
     var companyId = up.CompanyId; 

     return from c in context.Content 
       where c.CompanyId == companyId 
       && (up.AccessControl.Any(
        a=> 
         a.CompanyId == c.CompanyId && 
         a.DivisionId == c.DivisionId && 
         a.DepartmentId == c.DepartmentId) 
       || up.AccessControl.Any(
        a=>a.CompanyId == c.CompanyId && 
         a.DivisionId == c.DivisionId && 
         a.DepartmentId == null) 
       || up.AccessControl.Any(
        a=> 
         a.CompanyId == c.CompanyId && 
         a.DivisionId == null) 
       select c; 
    } 
} 

將使你回來是訪問的內容,如果:

  1. 該內容屬於用戶的公司。
  2. 用戶可訪問內容的公司,部門和部門
  3. 或者用戶可以訪問的公司和部門的內容(全系)
  4. 或者用戶能夠對公司訪問內容(各部門) [各部門,假設在這種情況下。]
+0

我有一些疑問,這將工作,因爲你在一個單一的查詢(「a.XXX」是內存中的值和'c.XXX'是數據庫值)混合LINQ到實體與LINQ到對象,這將可能會在運行時拋出異常。 – Slauma 2013-03-02 18:53:42

+0

我不確定您的評論是否有效。這裏的所有東西都是IQueryable,因此應該能夠一直生成SQL直至實際的請求。我一直在構建一個測試實現,並且到目前爲止它看起來會起作用。當然,我喜歡戴維斯布羅薩爾的建議甚至比我的解決方案更好。 – 2013-03-03 13:27:05

+0

'up.AccessControl'不是'IQueryable ',它只是內存中由延遲加載填充的本地集合。我會期望臭名昭着的「*無法創建恆定價值bla bla ... *」異常(http://stackoverflow.com/questions/7220867/unable-to-create-a-constant-value-of-type-type -only原語類型 - 例如-AS)。但也許我錯了... – Slauma 2013-03-03 21:14:08

0

你應該尋找到一個政策和基於屬性的解決方案,它獨立於您的應用程序,在那裏你可以寫授權策略,如

用戶可以訪問倉庫中的內容如果content.department == user.department & & content.company == user.company。

XACML聽起來像是一個完美的模型。我寫了這個演示,我根據購買者,採購訂單的數量,位置和狀態對採購訂單進行了訪問控制。我不需要更改應用程序代碼,因爲我在外部使用XACML。