MultiTenant应用程序阻止来自共享数据库中其他租户的租户访问数据

时间:2015-06-10 01:34:47

标签: asp.net-mvc entity-framework ef-code-first ef-migrations multi-tenant

我正在处理租户申请,我想知道如何阻止租户访问其他租户数据。

首先,让我揭露一些事实:

  1. 该应用程序不是免费的,100%肯定是恶意用户是客户端。
  2. 所有主键/标识都是整数(Guid解决了这个问题但我们现在无法改变)。
  3. 该应用使用共享数据库和共享架构。
  4. 所有租户都是拥有多家商店的商业集团。
  5. 我使用Forgery ......
  6. 我通过下拉列表选择了远程数据,如果您有一点知识,可以轻松更改来自其他租户的ID和访问数据f * ck其他租户数据。

    我认为首先要检查每个远程领域,但这很烦人......

    因此,我使用模型约定复合键构建了与代码优先迁移兼容的解决方案,很少有测试,按预期工作。

      

    以下是解决方案:

    会议等级

    public class TenantSharedDatabaseSharedSchemaConvention<T> : Convention where T : class
    {
        public Expression<Func<T, object>> PrimaryKey { get; private set; }
    
        public Expression<Func<T, object>> TenantKey { get; private set; }
    
        public TenantSharedDatabaseSharedSchemaConvention(Expression<Func<T, object>> primaryKey, Expression<Func<T, object>> tenantKey)
        {
            this.PrimaryKey = primaryKey;
            this.TenantKey = tenantKey;
    
            base.Types<T>().Configure(m =>
            {
                var indexName = string.Format("IX_{0}_{1}", "Id", "CompanyId");
    
                m.Property(this.PrimaryKey).IsKey().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).HasColumnOrder(0).HasColumnAnnotation("Index", new IndexAnnotation(new[] {
                    new IndexAttribute(indexName, 0) { IsUnique = true }
                }));
    
                m.Property(this.TenantKey).IsKey().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None).HasColumnOrder(1).HasColumnAnnotation("Index", new IndexAnnotation(new[] {
                    new IndexAttribute(indexName, 1) { IsUnique = true }
                }));
            });
        }
    }
    

    Convetion Registration

    **在约定寄存器中,我传递两个属性,第一个是主键,第二个是租户ID。

    modelBuilder.Conventions.Add(new TenantSharedDatabaseSharedSchemaConvention<BaseEntity>(m => m.Id, m => m.CompanyId));
    

    基本实体模型

    public class BaseEntity
    {
        public int Id { get; set; }
    
        public int CompanyId { get; set; }
    
        public Company Company { get; set; }
    }
    

    订单实体(示例)

    **在这里,我引用货币和客户与公司和所有工作按预期...

    public class Order : BaseEntity
    {
        [Required]
        public int CurrencyId { get; set; }
    
        [ForeignKey("CompanyId, CurrencyId")]
        public virtual Currency Currency { get; set; }
    
        [Required]
        public int ClientId { get; set; }
    
        [ForeignKey("CompanyId, ClientId")]
        public virtual Client Client { get; set; }
    
        public string Description { get; set; }
    }
    
    1. 对性能有影响吗?
    2. 检查每个远程字段是否有任何不利之处?
    3. 有人有同样的想法和/或问题并附带另一种解决方案吗?

1 个答案:

答案 0 :(得分:1)

恕我直言,在应用程序的任何地方,您将拥有一个映射,指出用户x有权管理或访问租户a(,b)。在您的业务层中,您应该检查用户是否有权使用伪造的ID查看数据。在您的情况下,伪造的我将属于用户无权访问的另一个租户,因此您将返回未经授权的/安全违规例外。

HTH