使用ASP.NET MVC设置路由{tenant} / {controller} / {action} / {id}?

时间:2009-11-09 09:15:39

标签: asp.net-mvc asp.net-mvc-routing multi-tenant

我想设置一个多租户ASP.NET MVC应用程序。理想情况下,此应用会有{tenant}/{controller}/{action}/{id}的路由,每个tenant代表应用的逻辑实例(只是独立的多用户帐户)

细粒度的细节对我来说还是很不清楚。任何可用于使用ASP.NET MVC设置此多租户方案的指南?

2 个答案:

答案 0 :(得分:12)

我目前正在使用ASP.Net MVC,Forms身份验证和用于Membership / Roles / Profile的SQL提供程序开展类似的项目。这是我采取的方法:

  1. 将默认路线注册为“{tenant} / {controller} / {action} / {id}

  2. 更改标准MVC模板附带的FormsAuthenticationService的默认行为。它应该将身份验证票证的UserData设置为包含租户名称(来自您的路由)。

    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. 在您的global.asax文件中进行一些租户安全检查,并允许在一个成员资格数据库中的租户之间分配用户

    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. 对每个租户数据进行分区。这有两个选择:

    4A。为每个租户使用单独的数据库。这为您的租户提供了最佳的数据安全性。在共享成员资格数据库中,添加一个表,该表在每个租户的唯一appid上键入,并使用此表存储和检索基于当前租户的连接字符串。

    4b中。将所有数据存储在一个数据库中,并将每个表键入唯一的租户ID。这为您的租户提供的数据安全性略低,但只使用一个SQL Server许可证。

答案 1 :(得分:2)

你很难find these links useful