【问题标题】:Storing Admin Accounts and Root Sites with Multi-Tenanted Site使用多租户站点存储管理员帐户和根站点
【发布时间】:2014-03-19 08:58:06
【问题描述】:

我正在创建一个多租户的 ASP.NET MVC 网站。

  1. 站点是分层的,所有站点都不可避免地指向一个“根”站点。
  2. 创建超级管理员用户。

是否有建议的方法来处理这些对象的初始创建?以下是我看到的选项:

  1. 将它们存储在 Web.config 中(但如果我存储超级管理员的密码,它们是否安全?)
  2. 在 Seeding 方法中创建所有这些对象(我使用的是 Entity Framework CodeFirst)。
  3. 使用 PreApplicationStartMethod 确保它们存在。

这里的标准方法是什么?

【问题讨论】:

  • 你有没有考虑过使用类似SimpleMembershipProvider的东西?
  • 我正在使用身份(这是 SimpleMembership 的升级版)-但这并不能解决我的问题-我认为该站点需要能够拥有超级管理员而不直接依赖身份框架 - 否则,如何创建第一个超级管理员?
  • 我没有使用Identity,所以我不确定我的建议是否适用于您的场景,但首先 - 您并不真的希望通过播种来完成此操作。一般来说,播种是为了开发目的,以便使用一些虚拟数据。 web.config 也是一个不好的地方。你可以用SimpleMembershipProviderIdentity 做什么是这样的:odetocode.com/blogs/scott/archive/2012/09/05/…
  • 并且还使用类似这样的东西:if (!context.Database.Exists()) { // Create the SimpleMembership database without Entity Framework migration schema ((IObjectContextAdapter)context).ObjectContext.CreateDatabase(); } 我认为这是更优雅的方式,因为这样你就可以将事情分开。
  • 这正是我在我的项目中所做的。我将发布我如何使用SimpleMembershipProvider 完成此操作的答案,因为它非常大,看看您是否可以调整它以与Identity 一起使用,如果它也可以与Identity 一起使用,请提供反馈:)

标签: c# asp.net-mvc multi-tenant


【解决方案1】:

这就是我使用SimpleMembershipProvider 解决此问题的方法,如果它们足够相似,也许您可​​以根据需要轻松调整此代码:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
    {
        private static SimpleMembershipInitializer _initializer;
        private static object _initializerLock = new object();
        private static bool _isInitialized;

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Ensure ASP.NET Simple Membership is initialized only once per app start
            LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
        }

        private class SimpleMembershipInitializer
        {
            public SimpleMembershipInitializer()
            {
                Database.SetInitializer<MyDbContext>(null);

                try
                {
                    using (var context = new MyDbContext())
                    {
                        if (!context.Database.Exists())
                        {
                            // Create the SimpleMembership database without Entity Framework migration schema
                            ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                        }
                    }

                    WebSecurity.InitializeDatabaseConnection("DAL.MyDbContext", "UserProfiles", "UserId", "UserName", autoCreateTables: true);
                    if (!Roles.RoleExists("SuperAdmin"))
                    {
                        Roles.CreateRole("SuperAdmin");
                        WebSecurity.CreateUserAndAccount("SuperAdmin", "12345");
                        Roles.AddUsersToRole(new[] { "SuperAdmin" }, "SuperAdmin");
                    }

                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
                }
            }
        }
    }

这是在我的主项目文件夹Filters 中。然后在Global.asax.cs

 protected void Application_Start()
    {
        //All the other stuff..
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    }

【讨论】:

  • 为什么要使用过滤器而不是仅仅将(例如)SimpleMembershipInitializer() 方法放在 Application_start() 方法中? Application_Start() 不是只在应用启动时运行吗?
  • @William 老实说,这段代码的更多内容是我自己获取的,而不是我自己创建的。我可以尝试抛出一些答案,但快速检查表明有关于这个主题的好文章可以给你这些答案,所以在那里更好地搜索。似乎如果您的会员提供者没有在全球范围内初始化,您会遇到很多麻烦。
猜你喜欢
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-07
  • 2012-06-30
相关资源
最近更新 更多