使用 ASP.NET MVC Identity 2.0 播种和登录默认用户的合适位置在哪里?

Where is the appropriate spot to seed and login a default user with ASP.NET MVC Identity 2.0?

我有一个使用 Identity 2.0 和 Owin 的应用程序。

我希望应用程序在开发过程中为默认用户设定种子并自动登录(我用 #if DEBUG 条件包装方法及其调用)。

我尝试将以下方法添加到 IdentityConfig.csApplicationUserManager.Create 方法中,但是在调用它之后, HttpContext.Current.User 仍然是空的打电话。

private void SeedAndLoginDefaultUser()
{
  var user = this.FindByName("***");
  if (user == null)
    this.Create(new ApplicationUser { /* ... */ }, "***");

  using (var signInManager = new ApplicationSignInManager(this, 
      HttpContext.Current.GetOwinContext().Authentication))
    signInManager.PasswordSignIn(user.UserName, "***", true, false);
}

但它不断地对用户进行身份验证。我确定应该有一个更合适的位置来执行此自动化操作。
P.S。从 Global.asax.csStartup.cs 做是不可能的,因为 owin 在那个阶段还没有初始化。

我尝试将其添加到 Context 初始化程序中,创建了用户,但登录失败。

更新

上回答:

实际上,UserManager 在 IdentityConfig.cs class 中被覆盖了。但我在想的是,每次调用 CustomAuthorize 下的方法时,您的解决方案都会检查用户是否存在。而我只想在应用程序启动时执行默认用户创建和登录。

更新 2

在我的数据库初始化程序中,我有一些关键的种子 tables,它有与用户相关的数据,这意味着,我必须在种子方法中创建用户。所以我现在的问题是,当我按照以下代码手动创建用户时:

public class Initializer : DropCreateDatabaseAlways<ApplicationDbContext>
{
  private static volatile bool processing;
  protected override void Seed(ApplicationDbContext context)
  {
    if (processing)
      return;
    processing = true;
    using (var um = ApplicationUserManager.Get())
    {
      var shimmy = new ApplicationUser
       {
         //Id = Guid.NewGuid().ToString(),
         FirstName = "Shimmy",
         LastName = "Weitzhandler",
         UserName = "***",
         Email = "***",
         //EmailConfirmed = true,
       };
      var task = um.CreateAsync(shimmy, "***");
      task.Wait();
      var result = task.Result;

      if (result.Succeeded)
      {
        using (var sm = ApplicationSignInManager.Get())
        {
          var siTask = sm.SignInAsync(shimmy, true, true);
          siTask.Wait();
          if (siTask.Exception != null)
          {
            throw siTask.Exception;
          }
        }
      }
      else
      {
        throw new InvalidOperationException();
      }
    }

    //seed my tables
    processing = false;
  }
}

如您所见,我什至添加了一个静态成员来避免循环返回初始化程序,但我相信它仍然无济于事。 因为当我尝试手动创建用户时(添加到 Users table,使用 UserManager.PasswordHasher,我无法登录该帐户。 但是上面代码的问题是我从 Seed 调用它,我怀疑当我尝试创建用户时它在内部回调自己,然后它卡住了。 我正在寻找的解决方案是如何手动创建用户并能够登录到该帐户。我可能在密码散列/用户验证/其他方面遗漏了一些要点。

您需要在默认授权开始之前执行此操作。为此,最简单的方法是创建您自己的 AuthorizeAttribute。

public class MyCustomAuthorizeAttribute: AuthorizeAttribute
{
   protected override bool AuthorizeCore(HttpContextBase httpContext)
   {
      #if DEBUG
        return true;
      #else

      return base.AuthorizeCore(httpContext);
   }

   public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
   {
      #if DEBUG
      // CHANGE TO YOUR USER MANAGER
      var userManger = filterContext.HttpContext.GetOwinContext().GetUserManager<ApplicationUser>();

      var user = userManger.FindByName("***");
      if (user == null)
         this.Create(new ApplicationUser {/* ... */}, "***");

      using(var signInManager = new ApplicationSignInManager(userManger, filterContext.HttpContext.GetOwinContext().Authentication))
         signInManager.PasswordSignIn(user.UserName, "***", true, false);

      return;
      #endif

      return base.OnAuthorization(filterContext);
   }
}

然后将所有现有的 Authorize 属性替换为您自己的属性,即

[MyCustomAuthorize]

[MyCustomAuthorize(Roles = "ROLENAME")]

解决方案 2:

如果不想为每个请求都登录,你可以跳过它,但你仍然需要从数据库中获取用户。为 getUser 实现您的服务。否则,您可以使用名称和角色(如有必要)对用户进行硬编码。

public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
    #if DEBUG
    // CHANGE TO YOUR USER MANAGER
    var user = GETUSER("");
    var principal = new GenericPrincipal(new GenericIdentity(user.Name), new[] { user.RoleName });

    Thread.CurrentPrincipal = principal;
    HttpContext.Current.User = principal;

    return;
    #endif

    return base.OnAuthorization(filterContext);
}