Utilisateur.Identité.GetUserId () renvoie null après une connexion réussie
j'ai défini une variable temp pour obtenir l'identifiant de l'utilisateur courant, elle renvoie toujours null.
Voici la capture d'écran:
Pourquoi?
mise à jour:
//
// 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." });
}
}
UPDATE 2:
côté client, j'utilise ajax pour me connecter à /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 sur le côté client:
var signalR = $.connection.chat;
var signin = function (callback) {
$.connection.hub.start().done(function () {
signalR.server.signinToSignalR();
callback()
})
};
SignalR sur le côté serveur:
public void SigninToSignalR()
{
// this's always null
string userId = HttpContext.Current.User.Identity.GetUserId();
}
7 réponses
en Fait, l'utilisateur est signé à - pas dans le contexte de l' la requête actuelle(POST /Account/Login
demande), où User.Identity
obtient ses données. Si vous voulez extraire l'id de l'utilisateur en train d'essayer de (et apparemment réussir) pour vous inscrire, vous devez le faire d'une autre façon, comme détourner un pas à l'intérieur de l'appel à SignInManager.PasswordSignInAsync
. Si vous êtes à la mise en œuvre de votre propre MembershipProvider
, ce devrait être facile.
Sinon, vous devrez attendre la prochaine demande(toute requête traitée par une méthode D'Action de Controller devrait faire l'affaire) utiliser User.Identity
dans la façon dont vous voulez.
Quelques explications
quand votre Login
la méthode est appelée, le contexte de la requête est déjà évalué et beaucoup de données sont disponibles. Par exemple, des en-têtes HTTP, des cookies, etc. C'est ici que se trouve toute l'information contextuelle., comme User.Identity
.
quand vous appelez SignInManager.PasswordSignInAsync(...)
, ce n' affecter les valeurs de l' contexte de demande, parce que cela n'aurait aucun sens – depuis le navigateur n'a pas changé son esprit sur ce qu'il a envoyé quelques millisecondes plus tôt. Que cela affecte l' contexte de la réponse pour ajouter un cookie contenant un identifiant utilisateur et de session. Ce cookie est ensuite envoyé au navigateur, qui le renvoie ensuite au serveur pour chaque demande. Donc toutes les requêtes plus tard que celle-ci (jusqu'à ce que l'utilisateur se déconnecte ou le cookie est trop vieux) inclura des informations pour le User.Identity
à interpréter.
essayez simplement ceci:
string userId = SignInManager
.AuthenticationManager
.AuthenticationResponseGrant.Identity.GetUserId();
Vous pouvez, dans votre cas, l'utilisation d'autres données pour trouver l'utilisateur qui vient de se connecter. Puisque nous savons que le login est réussi et que le nom d'utilisateur est unique, ce qui suit fonctionnera;
//
// 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." });
}
}
HttpContext.User = await _signInManager.CreateUserPrincipalAsync(user);
après avoir signé, vous pouvez utiliser le sign in manager pour créer le principal utilisateur et assigner manuellement le HttpContext.Référence de l'utilisateur
cela vous permettra alors d'accéder à l'ID utilisateur comme vous le feriez avec un normal signé à la page
var userId = userManager.GetUserId(HttpContext.User);
Oui, comme Anders l'a dit, Utilisateur.Identité et utilisateur.IsInRole ne fonctionnera pas dans la même action de connexion. Donc, vous devez rediriger vers une nouvelle action, donc à l'intérieur de l'action de connexion Ajouter:
return RedirectToAction ("MyNewLoginRoute", new {returl=returl });
ci-dessous un exemple de code:
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 });
Et Maintenant ajouter une nouvelle action LoginRoute comme ci-dessous :
// 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);
}
}
Espérons que cela pourrait aider quelqu'un.
je reçois à l'utilisateur de faire ce qui suit juste après, connectez-vous:
var userId = SignInManager.AuthenticationManager.AuthenticationResponseGrant.Identity.GetUserId();
var user = SignInManager.UserManager.Users.Where(x => x.Id.Equals(userId)).FirstOrDefault();
Voici ce qui a fonctionné pour moi:
await SignInManager.SignInAsync(user, isPersistent: true, rememberBrowser: false);
AuthenticationManager.User = new GenericPrincipal(AuthenticationManager.AuthenticationResponseGrant.Identity, null);
Une fois exécuté, vous obtenez l'état d'authentification pour la requête courante.