具有外部登录的 MVC 5 身份的 userLogins 始终为 0

MVC 5 Identity with external login has userLogins always 0

我有一个带有外部登录的 MVC 5 站点 运行 身份。我只是稍微修改了一下,将 f/l 姓名和用户名与电子邮件分开。

我没有注册新用户,我只是通过 Fackbook 登录...(这可能是问题所在?) 如果我通过 Facebook 登录,它会在身份 tables 中创建一个用户(但不会创建密码哈希)。

然而,当我导航到 'Manage' 控制器时,它显示

External Logins: 0 [ Manage ]

当我点击 'manage' 时,它会将我带到 'Manage/ManageLogins' 并显示一个 Facebook 按钮...但是在点击 FB 按钮后,我得到 'an error has occurred'

查看 Manage Controller,我发现此方法受到攻击,但它收集 userLogins 的地方却没有。

 // GET: /Manage/ManageLogins
    public async Task<ActionResult> ManageLogins(ManageMessageId? message)
    {
        ViewBag.StatusMessage =
            message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
            : message == ManageMessageId.Error ? "An error has occurred."
            : "";
        var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
        if (user == null)
        {
            return View("Error");
        }
    --> var userLogins = await UserManager.GetLoginsAsync(User.Identity.GetUserId()); <-- here it doesn't get any
        var otherLogins = AuthenticationManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList();
        ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1;
        return View(new ManageLoginsViewModel
        {
            CurrentLogins = userLogins,
            OtherLogins = otherLogins
        });
    }

注意:UserManager.GetLoginsAsync 总是返回 0 并且我已经验证 User.Identity.GetUserId() 正在返回用户的 ID...它只是没有得到用户。我刚刚用一个新创建的本地用户尝试了这个。

此代码仅在存在 userLogin 时显示 'remove' 按钮...但通过外部登录登录时未创建 userLogin。 这是正常的吗?我期待创建一个 userLogin 并引用到外部,但我不确定身份如何处理这方面...

我该如何解决这个问题,以便我的用户仍然可以取消关联他们的 FB 帐户?还是因为它是外部登录并且从未真正注册为本地帐户,所以没有真正的帐户可以取消关联?...这就是我所缺少的吗?这是预期的行为吗?

PS:我必须在 AccountContoller 的 ExternalLogin 方法中的 ChallengeResult 调用之前添加一行代码来终止任何现有会话:

// POST: /Account/ExternalLogin
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLogin(string provider, string returnUrl)
    {
 here-->     ControllerContext.HttpContext.Session.RemoveAll();

        // Request a redirect to the external login provider
        return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
    }

这会导致任何问题吗?必须用这一行开箱即用地修复 Identity 似乎很奇怪..(虽然它被谈论了很多)

编辑: 我注意到在 'IdentityUserLogins' table 中,它显示了 'Facebook' 的 LoginProvider 并且 userId 是我的用户..但是,ApplicationUserId 字段为空.. 在放置 userid 时进入此字段后,'remove' 按钮会显示在管理页面中.... 我错过了什么? 为什么没有输入 applicationUserID?..默认身份的另一个修复?

Found the answer here

我已将我的身份模型移动到与 Web 项目分开的 'Data' 项目中。这个 post 中的人也有类似的问题,他的 Id 也为空。对 fluent-api 和 voila.

稍作改动
var user = modelBuilder.Entity<TUser>()
.ToTable("AspNetUsers");
user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
user.Property(u => u.UserName).IsRequired();

modelBuilder.Entity<TUserRole>()
.HasKey(r => new { r.UserId, r.RoleId })
.ToTable("AspNetUserRoles");

modelBuilder.Entity<TUserLogin>()
.HasKey(l => new { l.UserId, l.LoginProvider, l.ProviderKey})
.ToTable("AspNetUserLogins");

modelBuilder.Entity<TUserClaim>()
.ToTable("AspNetUserClaims");

var role = modelBuilder.Entity<TRole>()
.ToTable("AspNetRoles");
role.Property(r => r.Name).IsRequired();
role.HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId);

我敢于进行如下更改并且效果很好:

//modelBuilder.Entity<IdentityUser>().ToTable("Usuario", "dbo");
 var user = modelBuilder.Entity<IdentityUser>()
           .ToTable("Usuario", "dbo");

            user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);