Identity IdentityUser PasswordHash 什么时候更新?

When does Identity IdentityUser PasswordHash update?

我问这个的原因是因为我正在尝试创建一个 MVC app/WebApi 服务,使用 ExternalLogin 凭据,特别是 Intuit 外部凭据,并允许登录过程设置当前身份Web 应用程序,一旦通过它的三足 OAuth 流程登录到 Intuit。我这样做是使用 Dapper 作为后端,而不是 EntityFramework。

如果您为 Web ASP.Net Web 应用程序创建一个默认的新项目 API,它会创建一个 AccountController 并包含一个名为 GetInfo 的帐户管理调用。在该函数中,它会在设置本地登录提供程序信息之前检查 PasswordHash(PasswordHash 是 IdentityUser 的 属性):

        if (user.PasswordHash != null)
        {
            logins.Add(new UserLoginInfoViewModel
            {
                LoginProvider = LocalLoginProvider,
                ProviderKey = user.UserName,
            });
        }

所以,显然,管理 PasswordHash 的逻辑已经在别处说明了。那可能在哪里?我猜想,在使用 EntityFramework 的典型设置中,这是在 IdentityUser class 甚至 UserManager class(UserStore?)的内部某处处理的。我在源代码中找不到它。

在我使用 Dapper 的实现中,模仿 Microsoft.AspNet.Identity.EntityFramework;

中发生的事情
  1. PasswordHash的计算、设置、校验应该在哪里进行?
  2. 什么时候设置属性?

或者 - 我不担心这个,因为一些神秘的黑色操作进程为 Object 设置了它??

未设置密码,请在使用外部提供商登录后检查您的数据库。

发生的事情是:

  1. 用户想要登录
  2. 用户单击按钮以 Google/Facebook
  3. 登录
  4. Google/Facebook 登录后发回一个外部令牌和一些其他信息。
  5. 此令牌包含有关用户的信息,您的 MVC 应用程序将使用该信息对用户进行身份验证。 (用户声明,使用 cookie)
  6. 您的 MVC 应用程序将在数据库中检查帐户是否已存在。 6 如果不存在,它会提示用户填写将存储在您的数据库中的电子邮件地址(不必与 google/facebook 电子邮件相同)。

所有奇迹发生的过程都在 Owin.Security

身份验证过程在 ExternalLogin、ExternalLoginCallback 方法中。默认 MVC 模板附带的

   // POST: /Account/ExternalLogin
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLogin(string provider, string returnUrl)
    {
        // Request a redirect to the external login provider
        return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
    }

    // GET: /Account/ExternalLoginCallback
    [AllowAnonymous]
    public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (loginInfo == null)
        {
            return RedirectToAction("Login");
        }

        // Sign in the user with this external login provider if the user already has a login
        var user = await UserManager.FindAsync(loginInfo.Login);
        if (user != null)
        {
            await SignInAsync(user, isPersistent: false);
            return RedirectToLocal(returnUrl);
        }
        else
        {
            // If the user does not have an account, then prompt the user to create an account
            ViewBag.ReturnUrl = returnUrl;
            ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
            return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
        }
    }