如何在成功登录结果后立即在控制器中获取 Identity UserID?

how can I get Identity UserID in the controller right after a successful login result?

我正在使用 Identity v2 和 MVC 5 进行外部登录。

在我的外部登录回调函数中,我使用

登录用户
var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);

然后 result 有一个开关,在 success 的情况下我需要访问用户的 ID,但是 User.Identity.GetUserId(); 在这里给了我 null。

在这种情况下如何访问用户 ID?

好的,我找到了一个方法;我可以通过以下方式获得它:

var userID = UserManager.FindByEmail(loginInfo.Email).Id;

但是,我认为这不是最好的解决方案,因为我好像用两个查询访问了数据库。谁能提供更好的解决方案?

您可以使用以下代码。

Add function to ApplicationSignInManager class in 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);
}

Try ths 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;
        }

要在成功登录后立即获取索赔数据和有关登录身份的其他信息,无需访问数据库,只需访问signinManager.AuthenticationManager.AuthenticationResponseGrant.Identity.

例如,

switch (result) { case SignInStatus.Success: var userId = signinManager.AuthenticationManager.AuthenticationResponseGrant .Identity.GetUserId(); // ...

您还可以看到它在 this other question's answer 中用于在登录后立即向身份添加新声明 - AuthenticationManager.AuthenticationResponseGrant.Identity.AddClaims(freshClaims);

我使用 System.Security.Claims.ClaimTypes.NameIdentifier 对象来保留我的用户 ID

然后我创建了一个助手 class 来达到其中的值

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

我用

来称呼它
var user = UserHelper.GetUserId();

在 dotnet 5 中,我在使用 SignInManager 登录后遵循上下文

 var result =
            await _signInManager.PasswordSignInAsync(model.UserName, model.Password, true, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            var userId = _signInManager.UserManager.Users.FirstOrDefault()?.Id; }