User.Identity.GetUserId () возвращает null в AccountsController, но отлично работает в HomeController [duplicate]

Вместо этого используйте старый java.awt.FileDialog:

new java.awt.FileDialog((java.awt.Frame) null).setVisible(true);
27
задан Tân Nguyễn 27 November 2015 в 08:52
поделиться

7 ответов

На самом деле пользователь не подписал - не в контексте текущего запроса (запрос POST /Account/Login) , где User.Identity получает свои данные. Если вы хотите извлечь идентификатор пользователя, пытающегося в настоящее время (и, видимо, преуспевающего) для входа, вам нужно сделать это каким-то другим способом, например, захватить какой-то шаг внутри вызова SignInManager.PasswordSignInAsync , Если вы реализуете свой собственный MembershipProvider, это должно быть легко.

В противном случае вам придется ждать следующего запроса (любой запрос, обработанный каким-либо методом Action Controller, должен делать все) / g2] использовать User.Identity так, как вы хотите.

Некоторое добавленное объяснение

Когда ваш метод Login вызывается, контекст запроса уже оценивается и много данных. Например, заголовки HTTP, файлы cookie и т. Д. Это где вся контекстная информация найдена, как User.Identity.

Когда вы вызываете SignInManager.PasswordSignInAsync(...), это не влияет на значения контекста запроса, потому что это не имеет смысла - поскольку браузер не изменил свое мнение о том, что он отправил несколько миллисекунд назад. На что он влияет, это контекст ответа для добавления файла cookie, содержащего некоторый идентификатор пользователя и сеанса. Этот файл cookie затем отправляется в браузер, который затем отправляет его на сервер для каждого последующего запроса. Таким образом, все запросы позже этого (пока пользователь не выберет или cookie не станет слишком старым) будет содержать информацию для User.Identity для интерпретации.

23
ответ дан Anders Tornblad 22 August 2018 в 20:23
поделиться
  • 1
    Благодаря! Можете ли вы объяснить мне больше о the current request и the next request? Когда запрос называется current request или next request? – Tân Nguyễn 27 November 2015 в 08:24
  • 2
    Ну, это просто базовый английский и временный характер. "Ток" request - это HTTP-запрос, который обрабатывает ваш код в настоящее время - в этом случае это запрос POST /Account/Login. Под заголовком "next" запрос Я просто хочу сказать, что следующий запрос должен появиться в какой-то более поздний момент времени (от микросекунд позже до нескольких дней) ... – Anders Tornblad 27 November 2015 в 08:26
  • 3
    я. Я думаю, что что-то может быть неправильно. Я приведу вам пример. На стороне клиента я использую ajax для подключения к /Account/Login. После успешного входа я снова использую ajax для соединения с концентратором signalR (/Hubs/ChatHub.cs). Я определил метод для получения userId, но он все равно null. public void SigninToSignalR() { string userId = HttpContext.Current.User.Identity.GetUserId(); } – Tân Nguyễn 27 November 2015 в 08:34
  • 4
    Затем я попытался получить userId в представлении: @{ string userId = User.Identity.GetUserId(); }. После обновления страницы она остается пустой. – Tân Nguyễn 27 November 2015 в 08:35
  • 5
    Это та же самая причина, по которой вам нужно сделать переадресацию после выхода из системы; выход из системы происходит после того, как был сконструирован контекст HTTP, и если вы выходите из системы, только следующий запрос будет фактически находиться в отключенном контексте. – Charleh 7 October 2016 в 07:41

Да, как сказал Андерс, User.Identity и User.IsInRole не будут работать внутри одного и того же действия входа. Итак, вам нужно перенаправить на новое действие, поэтому внутри действия входа добавить:

вернуть RedirectToAction («MyNewLoginRoute», new {returnUrl = returnUrl});

ниже - это код Пример:

        var result =  SignInManager.PasswordSignIn(model.Email, model.Password, model.RememberMe, shouldLockout: false);

        switch (result)
        {
            case SignInStatus.Success:

// below is the new line modification
      return RedirectToAction("LoginRoute", new {returnUrl=returnUrl });

И теперь добавьте новое действие LoginRoute, как показано ниже:

 // below method is new to get the UserId and Role
 public ActionResult LoginRoute(string returnUrl)  //this method is new
    {
        if (String.IsNullOrWhiteSpace(returnUrl))
        {
            if (User.IsInRole("Admin"))
            {
                return RedirectToLocal("/Admin");
            }
            else if (User.IsInRole("Partner"))
            {
                return RedirectToLocal("/Partner/Index/");
            }
            else if (User.IsInRole("EndUser"))
            {
                ApplicationDbContext db = new ApplicationDbContext();

            // know the partner
                int partnerID = db.Users.Where(x => x.UserName == User.Identity.Name).FirstOrDefault().PartnersTBLID;
                return RedirectToLocal("/Partner/List/" + partnerID.ToString());
            }

        }
        else
        {
            return RedirectToLocal(returnUrl);
        }
    }

Надеюсь, это может кому-то помочь.

1
ответ дан Bashar Abu Shamaa 22 August 2018 в 20:23
поделиться

Попробуйте это:

string userId = SignInManager
.AuthenticationManager
.AuthenticationResponseGrant.Identity.GetUserId();
15
ответ дан Beedjees 22 August 2018 в 20:23
поделиться

Вот что сработало для меня:

await SignInManager.SignInAsync(user, isPersistent: true, rememberBrowser: false);

AuthenticationManager.User = new GenericPrincipal(AuthenticationManager.AuthenticationResponseGrant.Identity, null);

После выполнения вы получите аутентифицированное состояние для текущего запроса.

0
ответ дан Dmitry Duka 22 August 2018 в 20:23
поделиться
HttpContext.User = await _signInManager.CreateUserPrincipalAsync(user);

После входа в систему вы можете использовать диспетчер значков для создания принципала пользователя и вручную назначить ссылку HttpContext.User

. Это позволит вам получить доступ к идентификатору пользователя, как если бы вы нормальная подпись на странице

var userId = userManager.GetUserId(HttpContext.User);
2
ответ дан Dustin Gamester 22 August 2018 в 20:23
поделиться
  • 1
    Мне нравится этот ответ, так как он хорошо связан с уже имеющим пользовательский объект во многих случаях. – Arian Kulp 4 May 2018 в 21:02

В вашем случае вы можете использовать другие данные, чтобы найти пользователя, который только что вошел в систему. Поскольку мы знаем, что логин успешно и имя пользователя уникальное, будет работать следующее:

 //
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (!ModelState.IsValid)
    {
        return Json(new { success = false, ex = "Fail to login." });
    }

    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, isPersistent: true, shouldLockout: false);
    switch (result)
    {
        case SignInStatus.Success:
            string userId = UserManager.FindByName(model.Email)?.Id;
            return Json(new { success = true });
        case SignInStatus.Failure:
            return Json(new { success = false, ex = "Email or password was incorrect." });
        default:
            return Json(new { success = false, ex = "Fail to login." });
    }
}
7
ответ дан Martijn Lentink 22 August 2018 в 20:23
поделиться

После входа в систему пользователь получает следующие права:

var userId = SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity.GetUserId();
var user = SignInManager.UserManager.Users.Where(x => x.Id.Equals(userId)).FirstOrDefault();
0
ответ дан wecky 22 August 2018 в 20:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: