La aplicación MultiTenant previene los datos de acceso de inquilinos de otros inquilinos en la base de datos compartida

Estoy trabajando en una aplicación de inquilino y me preguntaba cómo puedo bloquear el acceso de inquilino a otros datos de inquilino.

Primero, déjenme exponer algunos hechos:

La aplicación no es gratuita, 100% seguro de que el usuario malintencionado es un cliente.Todas las claves principales / identidad son enteros (Guid resuelve este problema pero no podemos cambiar en este momento).La aplicación utiliza una base de datos compartida y un esquema compartido.Todos los inquilinos son grupos empresariales que poseen varias tiendas.Estoy usando Falsificación ...

tengo algunosdatos remotos elegido pordesplegable y es fácil cambiar los datos de identificación y acceso de otros inquilinos, si tiene un poco de conocimiento puede coger los datos de otros inquilinos.

Lo primero que creo fue comprobar cada campo remoto, pero esto es un poco molesto ...

Entonces construyo una solución compatible conCode First Migrations utilizandoModelo de convenio yClaves compuestas, pocos probados, trabajando como se esperaba.

Aquí está la solución:

Clase de convención

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 }
            }));
        });
    }
}

Registro de convección:

** En el registro de convenciones, paso dos propiedades, primero la clave principal y la segunda es la identificación del inquilino.

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

Modelo de entidad base

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

    public int CompanyId { get; set; }

    public Company Company { get; set; }
}

Entidad de pedido (ejemplo)

** Aquí hago referencia a la moneda y al cliente con la empresa y todo funciona como se espera ...

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; }
}
¿Hay algún impacto en el rendimiento?¿Hay alguna desventaja en comparación con verificar cada campo remoto?¿Alguien tiene la misma idea y / o problema y vino con otra solución?

Respuestas a la pregunta(1)

Su respuesta a la pregunta