【问题标题】:How to handle authentication in multi-tenant MVC 5 app如何在多租户 MVC 5 应用程序中处理身份验证
【发布时间】:2014-11-28 01:41:42
【问题描述】:

我正在尝试构建一个多租户 mvc 5 站点,该站点使用单个数据库并在 Sql Server 中按模式区分租户。 我从默认的 Mvc 5 模板开始,并更新了提供的 ApplicationDBContext 以获取指定用于该租户的架构的字符串,就像这样。

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    private string _tenantSchema;
    public ApplicationDbContext(string tenantSchema)
        : base("Dev", throwIfV1Schema: false)
    {
        _tenantSchema = tenantSchema;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema(_tenantSchema);
        base.OnModelCreating(modelBuilder);
    }

    public static ApplicationDbContext Create(string tenantSchema)
    {
        return new ApplicationDbContext(tenantSchema);
    }
}

然后在 App_Start\IdentityConfig.cs 中,我更新了 ApplicationUserClass 的 Create 方法,以使用 Request.Host 值的第一部分作为租户架构,就像这样

 public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {
        var tenantSchema = context.Request.Host.Value.Split('.')[0];
        var ctx = new ApplicationDbContext(tenantSchema);

        var userStore = new UserStore<ApplicationUser>(ctx);
        var manager = new ApplicationUserManager(userStore);

因此,如果我要登录到 site1.mysite.dev,它将针对 site1 架构中的表进行身份验证,即 sql server。

当我启动站点并使用 site1 子域访问它时,它正确地使用 site1 Schema 对我进行身份验证。但是,如果我在浏览器地址栏中更改 url 并再次登录,它仍然会针对 site1 架构进行验证。

如何配置应用程序以用于更正架构以检查每个请求的身份验证?

【问题讨论】:

  • 您是否已调试并验证是否在每个请求上都调用了 Create?如果是这样,tenantSchema 是否真的有你期望的数据?如果每个请求都没有调用它,那么您配置错误,请显示您的 Startup.Auth

标签: asp.net-mvc entity-framework authentication asp.net-identity multi-tenant


【解决方案1】:

虽然您展示的代码应该可以工作(但很难说,因为您遗漏了其他关键部分,例如 Startup.Auth),但我不会这样做。我会改为将您的 ApplicationDbContext.Create 方法更改为:

public static ApplicationDbContext Create(
           IdentityFactoryOptions<ApplicationDbContext> options, IOwinContext context)
{
    var tenantSchema = context.Request.Host.Value.Split('.')[0];
    return new ApplicationDbContext(tenantSchema);
}

然后我会这样更改我的 Startup.Auth:

app.CreatePerOwinContext<ApplicationDbContext>(ApplicationDbContext.Create); <---
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

并将其他所有内容保留为默认值。具体来说:

public static ApplicationUserManager Create(
         IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
{
    var manager = new ApplicationUserManager(
                  new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
   ....

但是,您的真正问题很可能是您的模型构建器在第一次创建时被缓存在应用程序域中。此处的文档中对此进行了引用:

http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext.onmodelcreating(v=vs.113).aspx

通常,此方法仅在派生上下文的第一个实例创建时调用一次。然后缓存该上下文的模型,并用于应用程序域中上下文的所有进一步实例。可以通过在给定的 ModelBuidler 上设置 ModelCaching 属性来禁用此缓存,但请注意,这会严重降低性能。通过直接使用 DbModelBuilder 和 DbContextFactory 类可以更好地控制缓存。

在 EF codeplex 网站上,实际上有一个关于 EF 和多租户使用(此处无法详述)的主题的精彩讨论:

https://entityframework.codeplex.com/discussions/462765

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-05
    • 2015-03-20
    • 1970-01-01
    • 2021-02-12
    • 2013-03-13
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    相关资源
    最近更新 更多