2012-04-17 81 views
1

我想詢問您對我處理多租戶的方式的看法。我「米使用MVC3(切換到MVC4)和EF作爲我的後端我使用一個單一的應用程序,共享模式多租戶下面是代碼:。在MVC上處理多租戶

public abstract class Service<T> where T : Entity 
{ 
    private Repository<T> _repo; 
    public Service() 
    { 
     _repo = new Repository<T>(); 
    } 

    public bool Authenticate(int id) 
    { 
     //var companyInfo = _authorizationRepository.GetApiKey(apiKey); 
     int tenantId = 0; // replaced by companyInfo using repository 
     var entity = _repo.GetQuery(tenantId).Where(e => e.Id == id).First(); 

     if (tenantId != entity.TenantId) 
      throw new ArgumentException(); 

     return true; 
    } 
} 

public class EmployeeService : Service<Employee> 
{ 
    private EmployeeRepository employeeRepository; 
    public EmployeeService() 
    { 
     employeeRepository = new EmployeeRepository(); 
    } 

    public Employee GetEmployeeById(int employeeId) 
    { 
     this.Authenticate(employeeId); 
     return employeeRepository.GetById(employeeId); 
    } 
} 

public class Entity 
{ 
    public int Id { get; set; } 
    public int TenantId { get; set; } 
} 

當然DI會在那裏,以及但是簡單我在這裏(暫時)刪除了它們,我在服務層使用了泛型(對此感覺很髒),因爲我在比較TenantId和將在類上傳遞的正確實體時遇到了困難。這個使用FilterAttributes,但我沒有任何想法如何處理你的multitenancy問題?設計是否存在一些長期可能遇到的重要缺陷?如果你有一些使用FilterAttributes的示例,那將是一個很大的幫助。

Th anks!

+0

爲什麼Multitenancy甚至是Web應用程序中的一個問題? – Tejs 2012-04-17 14:32:40

+0

@Tejs對我來說關心的是我如何處理路由。基本上tenant1.domain.com和domain.com/tenant2都必須是有效的,並指向特定租戶 – MikeSW 2012-04-17 14:47:17

+0

這很酷,但該特定的URL方案與您決定使用的持久層無關。我想我想知道你的問題是什麼。 – Tejs 2012-04-17 14:48:23

回答

2

我們正在構建相當大的多租戶web應用程序。那麼它並不像看起來那麼簡單,但是一旦你建立了你的架構,它就很簡單。我們正在深入開發,但你可以看看nanocms.codeplex.com中的開源部分(我們沒有上傳數據庫噴射對接,我們將在幾天內)

由於這是一個相當廣泛的問題,我會嘗試總結一些問題和解決方案。

首先,您需要確定每個請求的租戶。我們有一個全局動作過濾器,用於解析url並將其與數據庫中的數據進行比較。當然,你必須緩存所有的數據,以免對數據庫進行調用。您不能在cookie或會話中保存任何內容,因爲用戶可以在當時訪問多個租戶。我建議你將這些數據放在HttpRequest Items中,這樣在請求中只做一次,但仍然可以使用這些數據。

對於驗證用戶必須是唯一的。你必須想,如果你想給每個租戶一些用戶不同的權利。如果是這樣,您必須編寫驗證碼甚至屬性,以便檢查他在當前租戶中的角色。在我們的應用中,當用戶認證時,我們創建會話對象。在對象中,我們有檢查租戶權限的靜態方法。

我建議你保持強制類型的HttpRequest項目。我們有:

public static int TenantID { 
    get { return System.Web.HttpContext.Current.Items.Contains("TenantID") ? Convert.ToInt32(System.Web.HttpContext.Current.Items["TenantID"]) : -1; } 
    set { 
     if (!System.Web.HttpContext.Current.Items.Contains("TenantID")) 
      System.Web.HttpContext.Current.Items.Add("TenantID", value); 
     System.Web.HttpContext.Current.Items["TenantID"] = value; 
    } 
} 
+0

感謝您的回覆Goran。但是,您如何檢查將要發佈的實體是否將不會轉向錯誤的租戶。例如,TenantA將插入/選擇一個項目,您如何確保TenantA不會選擇/插入TenantB的數據? – gnaungayan 2012-04-17 23:21:44

+0

請解釋一下您是否擔心交叉發佈的安全問題,或只是向正確的承租人提供正確的內容?爲了安全起見,您可以使用防僞標記來防止交叉帖子。爲了確保正確的內容,您必須在數據庫的每個父表中都有tenantId並相應地寫入查詢。 – 2012-04-18 07:21:27

+0

它更像你的第二個陳述。如果有一個網址www.site.com/Employees/1(這屬於TenantA數據),但TenantB已登錄並對該網址進行了硬編碼,那麼如何阻止他查看TenantA數據? – gnaungayan 2012-04-18 13:36:19