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

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

我希望应用程序为默认用户播种并在开发时自动登录(我用#if DEBUG条件包装方法及其调用).

我尝试将以下方法添加到IdentityConfig.csApplicationUserManager.Create方法,但在调用它之后,HttpContext.Current.User在下次调用时仍为null.

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);
}

但它一直在不断地对用户进行身份验证.我确信应该有一个更合适的位置来执行这种自动化.
附:从Global.asax.cs或Startup.cs这样做是不可能的,因为owin在那个阶段尚未初始化.

我尝试在Context初始化程序中添加它,用户被创建,但登录失败.

更新

this回答:

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

更新2

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

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;
  }
}

正如你所看到的,我甚至添加了一个静态成员来避免循环初始化器,但我相信它仍然无济于事.
因为当我尝试手动创建用户时(使用UserManager.PasswordHasher添加到Users表中,我无法登录该帐户).
但上面代码的问题是我从Seed调用它,我怀疑它在我尝试创建用户时会在内部调用它,然后它就会卡住.
我正在寻找的解决方案是如何手动创建用户并能够登录该帐户.我可能在密码散列/用户验证/其他任何问题上都缺少一点.

最佳答案 在默认的Autorization开始之前,您需要这样做.要做到这一点,最简单的方法是创建自己的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:

如果不想为每个请求登录,则可以跳过该请求,但仍需要从DB中获取用户.实现您的服务到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);
}
点赞