Приложение MultiTenant предотвращает доступ арендатора к данным других арендаторов в общей базе данных
Я работаю над приложением арендатора, и мне было интересно, как я могу заблокировать доступ арендатора к другим данным арендатора.
Во-первых, позвольте мне изложить некоторые факты:
Приложение не бесплатное, на 100% точно злоумышленник является клиентом.Все первичные ключи / идентификаторы являются целыми числами (Guid решает эту проблему, но мы не можем сейчас изменить).Приложение использует общую базу данных и общую схему.Все арендаторы - бизнес-группа, владеющая несколькими магазинами.Я использую подделку ...у меня есть немногоудаленные данные выбранопадать и легко изменять идентификаторы и данные доступа от других арендаторов, если у вас мало знаний, вы можете получить данные других арендаторов.
Первое, что я думаю, это проверить каждое удаленное поле, но это немного раздражает ...
Поэтому я создаю решение, совместимое сКод Первые Миграции с помощьюТиповая конвенция а такжеКомпозитные ключиМало кто тестировал, работает как положено.
Вот решение:
Конвенционный класс
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 }
}));
});
}
}
Конвекционная регистрация:
** В регистре соглашений я передаю два свойства: первый - первичный ключ, а второй - идентификатор арендатора.
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; }
}
Есть ли влияние на производительность?Есть ли недостаток по сравнению с проверкой каждого удаленного поля?У кого-то есть такая же идея и / или проблема, и они пришли с другим решением?