成功登录后,User.Identity.GetUserId()返回null

我已经定义了一个临时变量来获取当前用户ID,它总是返回null。

这是快照:

用户身份

为什么?

更新:

// // POST: /Account/Login [HttpPost] [AllowAnonymous] public async Task 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 } }); 

客户端SignalR:

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

服务器端的SignalR:

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

实际上,用户未登录 – 不在当前请求 POST /Account/Login请求)的上下文中,这是User.Identity获取其数据的位置。 如果要提取当前尝试(并且显然是成功)登录的用户的id,则需要以其他方式执行此操作,例如在对SignInManager.PasswordSignInAsync的调用中劫持某些步骤。 如果您要实现自己的MembershipProvider ,这应该很容易。

否则,您将不得不等待下一个请求 (某些Controller的Action方法处理的任何请求应该没问题)以您希望的方式使用User.Identity

一些补充说明

调用Login方法时,已经评估了请求上下文,并且有大量数据可用。 例如HTTP标头,cookie等。 这是找到所有上下文信息的地方,例如User.Identity

当你调用SignInManager.PasswordSignInAsync(...) ,这不会影响请求上下文的值,因为这没有任何意义 – 因为浏览器没有改变它几毫秒前发送的内容。 它影响的是添加包含一些用户和会话ID的cookie响应上下文 。 然后将此cookie发送到浏览器,然后浏览器将其发送回服务器以获取每个连续请求。 因此,所有晚于此的请求(直到用户退出或cookie过时)将包含User.Identity要解释的信息。

试试这个:

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

在您的情况下,您可以使用其他数据来查找刚刚登录的用户。由于我们知道登录成功且用户名是唯一的,因此以下内容将起作用;

  // // POST: /Account/Login [HttpPost] [AllowAnonymous] public async Task 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." }); } } 
 HttpContext.User = await _signInManager.CreateUserPrincipalAsync(user); 

登录后,您可以使用登录管理器创建用户主体并手动分配HttpContext.User引用

这将允许您像使用普通登录页面一样访问用户ID

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

是的,正如Anders所说,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); } } 

希望这可以帮助某人。

登录后,我让用户立即执行以下操作:

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

这对我有用:

 await SignInManager.SignInAsync(user, isPersistent: true, rememberBrowser: false); AuthenticationManager.User = new GenericPrincipal(AuthenticationManager.AuthenticationResponseGrant.Identity, null); 

执行后,您将获得当前请求的身份validation状态。