Подтвердить что ты не робот

User.Identity.GetUserId() возвращает null после успешного входа в систему

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

Вот снимок:

userId

Почему?

UPDATE:

    //
    // 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 = User.Identity.GetUserId();
                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." });
        }
    }

ОБНОВЛЕНИЕ 2:

На стороне клиента я использую ajax для подключения к /Account/Login:

var loginAjax = function (email, password, callback) {        
        $.ajax({
            url: '/Account/Login',
            type: 'POST',
            data: { Email: email, Password: password },
            success: function (data) {
                $('body').css('cursor', 'default');
                if (data.success) {                    
                    callback(true)
                } else {
                    $('#login-error').text(data.ex)
                }
            },
            error: function () {                
                $('#login-error').text('Không thể kết nối đến máy chủ.')
            }
        });
        callback(false)
    };


// I've got email and password in another function to check valid or not
loginAjax(email, password, function (success) {
            $('body').css('cursor', 'default');
            switch (success) {
                case true:
                    signin(function () {
                        $('.login').html('');
                        window.location.href = '/?type=Promotion';
                    });
                    break
                case false:                    
                    $('#Email-active').hide();
                    $('#Password-active').hide();
                    $('#Password').val('');
                    $('#login-btn').removeClass('disabled').attr('onclick', '$(this).addClass("disabled").removeAttr("onclick"); running()');
                    break
            }
        });

СигналR на стороне клиента:

var signalR = $.connection.chat;
var signin = function (callback) {
            $.connection.hub.start().done(function () {
                signalR.server.signinToSignalR();
                callback()
            })
        };

СигналR на стороне сервера:

public void SigninToSignalR()
    {
        // this always null
        string userId = HttpContext.Current.User.Identity.GetUserId();
    }
4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

Просто попробуйте следующее:

string userId = SignInManager
.AuthenticationManager
.AuthenticationResponseGrant.Identity.GetUserId();

Ответ 3

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

 //
// 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." });
    }
}

Ответ 4

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

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

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

Ответ 5

HttpContext.User = await _signInManager.CreateUserPrincipalAsync(user);

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

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

var userId = userManager.GetUserId(HttpContext.User);

Ответ 6

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

var userId = SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity.GetUserId();
var user = SignInManager.UserManager.Users.Where(x => x.Id.Equals(userId)).FirstOrDefault();