J'utilise Identity v2 et MVC 5 pour la connexion externe.
Dans ma fonction de rappel de connexion externe, je connecte l'utilisateur avec
var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
alors il y a un commutateur pour le result
, et j'ai besoin d'accéder à l'ID de l'utilisateur dans le cas success
, mais User.Identity.GetUserId();
me donne null ici.
Comment puis-je accéder à l'ID utilisateur dans ce cas?
Pour obtenir les données de réclamation et autres informations sur l'identité signée immédiatement lors d'une connexion réussie, sans accéder à la base de données, il suffit d'accéder à signinManager.AuthenticationManager.AuthenticationResponseGrant.Identity
.
Par exemple,
switch (result) { case SignInStatus.Success: var userId = signinManager.AuthenticationManager.AuthenticationResponseGrant .Identity.GetUserId(); // ...
Vous pouvez également le voir utilisé dans la réponse à cette autre question pour ajouter de nouvelles revendications à une identité immédiatement après la connexion - AuthenticationManager.AuthenticationResponseGrant.Identity.AddClaims(freshClaims);
J'utilise System.Security.Claims.ClaimTypes.NameIdentifier
objet pour conserver mon identifiant
Et j'ai créé une classe d'aide pour atteindre les valeurs qu'il contient
public class UserHelper
{
public static string GetUserId()
{
var identity = (System.Security.Claims.ClaimsPrincipal)System.Threading.Thread.CurrentPrincipal;
var principal = System.Threading.Thread.CurrentPrincipal as System.Security.Claims.ClaimsPrincipal;
var userId = identity.Claims.Where(c => c.Type == System.Security.Claims.ClaimTypes.NameIdentifier).Select(c => c.Value).SingleOrDefault();
return userId;
}
public static string GetUserName()
{
var identity = (System.Security.Claims.ClaimsPrincipal)System.Threading.Thread.CurrentPrincipal;
var principal = System.Threading.Thread.CurrentPrincipal as System.Security.Claims.ClaimsPrincipal;
var name = identity.Claims.Where(c => c.Type == System.Security.Claims.ClaimTypes.Name).Select(c => c.Value).SingleOrDefault();
return name;
}
public static string GetUserMail()
{
var identity = (System.Security.Claims.ClaimsPrincipal)System.Threading.Thread.CurrentPrincipal;
var principal = System.Threading.Thread.CurrentPrincipal as System.Security.Claims.ClaimsPrincipal;
var mail = identity.Claims.Where(c => c.Type == System.Security.Claims.ClaimTypes.Email).Select(c => c.Value).SingleOrDefault();
return mail;
}
}
et je l'appelle avec
var user = UserHelper.GetUserId();
vous pouvez utiliser le code ci-dessous.
Ajouter une fonction à la classe ApplicationSignInManager dans Identity.Config.cs
public override Task SignInAsync(ApplicationUser user, bool isPersistent, bool rememberBrowser)
{
var claims = new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Email, user.Email)
};
this.AuthenticationManager.User.AddIdentity(new ClaimsIdentity(claims));
return base.SignInAsync(user, isPersistent, rememberBrowser);
}
Essayez ce code
private ClaimsPrincipal GetCurrentUser()
{
var context = HttpContext.GetOwinContext();
if (context == null)
return null;
if (context.Authentication == null || context.Authentication.User == null)
return null;
return context.Authentication.User;
}
private string GetUserId()
{
var user = GetCurrentUser();
if (user == null)
return null;
var claim = user.Claims.FirstOrDefault(o => o.Type == ClaimTypes.NameIdentifier);
if (claim == null)
return null;
return claim.Value;
}
private string GetUserEmail()
{
var user = GetCurrentUser();
if (user == null)
return null;
var claim = user.Claims.FirstOrDefault(o => o.Type == ClaimTypes.Email);
if (claim == null)
return null;
return claim.Value;
}
OK, j'ai trouvé one way; Je peux l'obtenir via:
var userID = UserManager.FindByEmail(loginInfo.Email).Id;
Mais, je ne pense pas que ce soit la meilleure solution car il semble que j'ai frappé la base de données avec deux requêtes. Quelqu'un peut-il offrir une meilleure solution?