Идентификация MVC 5 с внешним входом всегда имеет userLogins 0

У меня есть сайт MVC 5, работающий с внешними логинами. Я лишь немного изменил его, чтобы имя пользователя и фамилия были отделены от электронной почты.

Я не регистрирую нового пользователя, я просто вхожу через Fackbook... (это может быть проблемой?) Если я вхожу через Facebook, он создает пользователя в таблицах идентификации (но не создается хэш пароля).

Однако, когда я перехожу к контроллеру «Управление», он показывает

External Logins: 0 [ Manage ]

И когда я нажимаю 'manage', я перехожу к «Управлению/управлению логинами» и вижу кнопку 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() возвращает идентификатор пользователя... он просто не получает пользователя. Я только что попробовал это с недавно созданным локальным пользователем.

Этот код показывает кнопку «удалить» только в том случае, если существует существующий логин пользователя... но логин пользователя не создается при входе в систему через внешний логин. Это нормально? Я ожидал, что userLogin будет создан и привязан к внешнему, но я не уверен, как идентификатор справляется с этим аспектом...

Как мне это сделать, чтобы мои пользователи могли по-прежнему отключать свою учетную запись FB? Или нет реальной учетной записи, от которой можно отсоединиться, поскольку это внешний вход в систему, и она никогда не регистрировалась как локальная учетная запись? ... Это то, что мне не хватает? Это ожидаемое поведение?

PS: мне пришлось добавить строку кода, чтобы убить любые существующие сеансы перед вызовом ChallengeResult в методе ExternalLogin AccountContoller как таковом:

// 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» отображается LoginProvider «Facebook», а userId — это мой пользователь. Однако поле ApplicationUserId имеет значение null.. после помещения идентификатора пользователя в это поле « Кнопка «удалить» отображается на странице управления... что мне не хватает? Как не вводится applicationUserID?.. еще одно исправление для удостоверения по умолчанию?


person Beau D'Amore    schedule 02.10.2015    source источник


Ответы (2)


Нашел ответ здесь

Я переместил свои модели идентификации в проект «Данные», отдельный от веб-проекта. У человека в этом посте была аналогичная проблема с его идентификатором, который также был нулевым. Небольшое изменение в fluent-api и вуаля.

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);
person Beau D'Amore    schedule 02.10.2015
comment
GetLoginsAsync должен возвращать 0 логинов, если пользователь вошел в систему с локальной (не внешней) учетной записью? - person Matthew; 01.06.2020
comment
Я не знаю. Хороший вопрос. - person Beau D'Amore; 02.06.2020

Я осмелился внести следующие изменения, и это сработало прекрасно:

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

            user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
person parismiguel    schedule 08.06.2016