Multi-tenancy is een van de moeilijkste zaken om achteraf in een applicatie in te bouwen. Met Hazina is het vanaf het begin ingebouwd. Elke query, elke mutatie, elke API-aanroep is automatisch beperkt tot de huidige tenant.
Hoe Het Werkt
Hazina gebruikt een middleware-gebaseerde aanpak voor tenantresolutie:
- Verzoek komt binnen met tenant-identificator (header, subdomein of JWT-claim)
- Middleware lost de tenant op en stelt de tenantcontext in
- Alle databasequeries worden automatisch gefilterd op TenantId
- Alle creaties stempelen automatisch de TenantId
- Kruis-tenant toegang is onmogelijk op frameworkniveau
Setup
builder.Services.AddGenericEntityApi<AppDbContext>();
builder.Services.AddScoped<ITenantContext, TenantContext>();
// Configure tenant resolution
builder.Services.AddTenantResolution(options => {
options.Strategy = TenantResolutionStrategy.Header;
options.HeaderName = "X-Tenant-Id";
// Of: options.Strategy = TenantResolutionStrategy.JwtClaim;
// Of: options.Strategy = TenantResolutionStrategy.Subdomain;
});
Entiteit Definitie
public class Customer : TenantEntityBase
{
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
}
Wat Er Achter de Schermen Gebeurt
// Wanneer Tenant A GET /api/customers aanroept
// Genereert Hazina: SELECT * FROM Customers WHERE TenantId = 'tenant-a'
// Wanneer Tenant A POST /api/customers aanroept
// Stelt Hazina automatisch in: customer.TenantId = 'tenant-a'
// Wanneer Tenant A GET /api/customers/42 aanroept
// Als klant 42 bij Tenant B hoort: 404 Niet Gevonden
// Niet 403 - de klant bestaat simpelweg niet in de wereld van Tenant A
Globale Entiteiten
Sommige entiteiten worden gedeeld tussen tenants (categorieën, instellingen sjablonen). Gebruik EntityBase voor die – ze omzeilen tenantfiltering:
public class GlobalCategory : EntityBase // Geen tenantfiltering
{
public string Name { get; set; } = string.Empty;
}
public class TenantCategory : TenantEntityBase // Tenant-gebonden
{
public string Name { get; set; } = string.Empty;
}
Multi-Tenancy Testen
// In je tests, stel gewoon de tenantcontext in:
var tenantContext = new TestTenantContext("test-tenant");
services.AddScoped<ITenantContext>(_ => tenantContext);
In de volgende post verkennen we RAG – Hazina’s Retrieval-Augmented Generation engine voor slimme documentzoekopdrachten.
Veelgestelde Vragen
Hazina beheert multi-tenancy door een middleware-gebaseerde aanpak te gebruiken die elke query, mutatie en API-aanroep automatisch beperkt tot de huidige tenant. Het lost tenant-identificatoren op via headers, subdomeinen of JWT-claims, waardoor databasequeries worden gefilterd op TenantId.
Het gebruik van Hazina vereenvoudigt de implementatie van multi-tenancy door kruis-tenant toegang op frameworkniveau uit te sluiten en automatisch tenantcontexten te beheren. Dit leidt tot verbeterde beveiliging en verminderde complexiteit in applicatieontwikkeling.
Om tenantresolutie in Hazina in te stellen, kun je de service configureren met builder.Services.AddTenantResolution() met je voorkeursstrategie, zoals Header, JWT Claim of Subdomein. Bijvoorbeeld, bij gebruik van Header specificeer je de headernaam zoals ‘X-Tenant-Id’ voor tenantidentificatie.
Globale Entiteiten in Hazina, zoals GlobalCategory, hebben geen tenantfiltering en kunnen gedeeld worden tussen tenants. Daarentegen zijn Tenant Entiteiten, zoals TenantCategory, gebonden aan individuele tenants, waardoor elke tenant alleen hun eigen data ziet.