2009-11-09 3 views
8

Je voudrais configurer une application ASP.NET MVC multi-locataire. Idéalement, cette application aurait une route avec {tenant}/{controller}/{action}/{id}, chaque tenant représentant une instance logique de l'application (simplement des comptes multi-utilisateurs indépendants)Configurer une route {tenant}/{controller}/{action}/{id} avec ASP.NET MVC?

Les détails à grain fin comment cela est encore tout à fait clair pour moi. Tout guide disponible pour configurer un tel schéma multi-locataire avec ASP.NET MVC?

Répondre

12

Je travaille actuellement sur un projet similaire en utilisant ASP.Net MVC, l'authentification par formulaires et les fournisseurs SQL pour Membership/Roles/Profile. Voici l'approche que je prends:

  1. enregistrer la route par défaut comme `{locataire}/{contrôleur}/{action}/{id}

  2. Modifier le comportement par défaut du FormsAuthenticationService qui vient avec le modèle MVC standard. Il doit définir les données utilisateur du ticket d'authentification pour inclure le nom du locataire (à partir de votre itinéraire).

    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. Dans votre fichier global.asax pour faire des vérifications de sécurité des locataires et permettre à des utilisateurs entre partitionnement des locataires dans une base de données de membres

    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. Partition de données chaque locataires. Voici deux options:

    4a. Utilisez une base de données distincte pour chaque locataire. Cela fournit la meilleure sécurité des données pour vos locataires. Dans la base de données des appartenances partagées, ajoutez une table codée sur un ID unique pour chaque locataire et utilisez cette table pour stocker et extraire la chaîne de connexion en fonction du locataire actuel.

    4b. Stockez toutes les données dans une base de données et entrez chaque table sur l'ID de locataire unique. Cela fournit légèrement moins de sécurité des données pour vos locataires, mais utilise une seule licence SQL Server.

+2

Désolé pour la réponse obsolète, mais Je travaille sur quelque chose de similaire et je pense que votre solution pourrait fonctionner, mais les docs disent qu'il n'y a qu'un seul fournisseur par défaut pour toutes les demandes arrivant sur le serveur. Donc, je pense que la définition du nom de l'application peut être une condition de concurrence. –

+0

CShipley, vous avez absolument raison. Lorsque j'ai utilisé cette solution moi-même, je suis presque devenu fou en essayant de résoudre les problèmes une fois que j'avais des utilisateurs simultanés de différents locataires. Je pense que le chemin à est d'écrire la pièce d'authentification à partir de zéro ou d'implémenter votre propre fournisseur d'adhésion. J'ai choisi de passer à une instance séparée de l'application pour chaque locataire jusqu'à ce que je puisse obtenir les détails d'un schéma d'authentification personnalisé élaboré. –

+0

Comment gérez-vous un utilisateur qui peut agir pour le compte de plus d'un locataire? –

2

Vous aurez probablement findtheselinksuseful.

+0

La question liée est pertinente en effet, mais sans bonnes réponses affichées malheureusement. En fait, le seul lien pertinent à un autre post, avec des réponses encore moins pertinentes :-( –

+0

Sux., Je suppose que je vais attendre jusqu'à ce que vous trouviez la réponse alors et je vais utiliser ce que vous trouvez alors.: D –

+0

Merci, ces liens sont géniaux! –

Questions connexes