2009-11-09 9 views
8

Vorrei installare un'app ASP.NET MVC multi-tenant. Idealmente, questa app avrebbe un percorso con {tenant}/{controller}/{action}/{id}, ogni tenant rappresenta un'istanza logica dell'app (semplicemente account multiutente indipendenti)Imposta una route {tenant}/{controller}/{action}/{id} con ASP.NET MVC?

I dettagli a grana fine come sono ancora abbastanza poco chiari per me. Qualche guida disponibile per configurare uno schema multi-tenant con ASP.NET MVC?

risposta

12

Attualmente sto lavorando a un progetto simile utilizzando ASP.Net MVC, Autenticazione moduli e provider SQL per Membership/Ruoli/Profilo. Ecco l'approccio sto prendendo:

  1. registrare il percorso predefinito come `{inquilino}/{Controller}/{action}/{id}

  2. modificare il comportamento predefinito del FormsAuthenticationService che viene con il modello MVC standard. Dovrebbe impostare i Dati utente del ticket di autenticazione per includere il nome del titolare (dal percorso).

    public void SignIn(string userName, bool createPersistentCookie, string tenantName) 
    { 
        var ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(30), 
                   createPersistentCookie, tenantName); 
        var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket)); 
        HttpContext.Current.Response.AppendCookie(cookie); 
    } 
    
  3. Nel file Global.asax per fare qualche controllo di sicurezza inquilino e consentire partizionamento degli utenti tra gli inquilini in un unico database di appartenenza

    protected void Application_AuthenticateRequest(object sender, EventArgs e) 
    { 
        //Since this method is called on every request 
        //we want to fail as early as possible 
        if (!Request.IsAuthenticated) return; 
        var route = RouteTable.Routes.GetRouteData(new HttpContextWrapper(Context)); 
        if (route == null || route.Route.GetType().Name == "IgnoreRouteInternal") return; 
        if (!(Context.User.Identity is FormsIdentity)) return; 
        //Get the current tenant specified in URL 
        var currentTenant = route.GetRequiredString("tenant"); 
        //Get the tenant that that the user is logged into 
        //from the Forms Authentication Ticket 
        var id = (FormsIdentity)Context.User.Identity; 
        var userTenant = id.Ticket.UserData; 
        if (userTenant.Trim().ToLower() != currentTenant.Trim().ToLower()) 
        { 
         //The user is attempting to access a different tenant 
         //than the one they logged into so sign them out 
         //an and redirect to the home page of the new tenant 
         //where they can sign back in (if they are authorized!) 
         FormsAuthentication.SignOut(); 
         Response.Redirect("/" + currentTenant); 
         return; 
        } 
        //Set the application of the Sql Providers 
        //to the current tenant to support partitioning 
        //of users between tenants. 
        Membership.ApplicationName = currentTenant; 
        Roles.ApplicationName = currentTenant; 
        ProfileManager.ApplicationName = currentTenant; 
    } 
    
  4. partizione ogni dati inquilini. Ecco due opzioni:

    4a. Utilizzare un database separato per ciascun titolare. Ciò fornisce la migliore sicurezza dei dati per i tuoi inquilini. Nel database di appartenenza condiviso, aggiungere una tabella con chiave sull'appid univoco per ciascun titolare e utilizzare questa tabella per archiviare e recuperare la stringa di connessione in base al tenant corrente.

    4b. Archivia tutti i dati in un database e digita ogni tabella sull'ID titolare unico. Ciò fornisce una sicurezza dei dati leggermente inferiore per i tenant ma utilizza una sola licenza di SQL Server.

+2

Ci scusiamo per la risposta non aggiornata, ma Sto lavorando su qualcosa di simile e penso che la tua soluzione potrebbe funzionare, tuttavia i documenti dicono che esiste un solo provider predefinito per tutte le richieste che arrivano sul server. Quindi, penso che impostare il nome dell'applicazione possa essere una condizione di competizione. –

+0

CShipley, hai assolutamente ragione. Quando ho usato questa soluzione, sono quasi diventato pazzo cercando di risolvere i problemi una volta che ho avuto utenti concorrenti da diversi inquilini. Penso che il modo per farlo sia scrivere da zero il pezzo di autenticazione o implementare il proprio provider di appartenenza. Ho scelto di passare a un'istanza separata dell'app per ciascun titolare finché non sono riuscito a ottenere i dettagli di uno schema di autenticazione personalizzato elaborato. –

+0

Come gestisci un utente che può agire per conto di più di un titolare? –

2

Si verificherà findtheselinksuseful.

+0

La domanda collegata è pertinente in effetti, ma purtroppo non ci sono buone risposte pubblicate. In realtà, l'unico post rilevante rimanda a un altro post, con anche risposte meno rilevanti :-( –

+0

Quel sux. Immagino che aspetterò fino a trovare la risposta, quindi userò ciò che trovi allora.: D –

+0

Grazie, questi link sono fantastici! –