Cómo obtener el ID de usuario conectado actualmente en ASP.NET Core

179

He hecho esto antes con MVC5 usando User.Identity.GetUserId()pero eso no parece funcionar aquí. El User.Identityno tiene el GetUserId()método

estoy usando Microsoft.AspNet.Identity

MRainzo
fuente
2
prueba esto System.Web.HttpContext.Current.User.Identity.Name?
Pravin Deshmukh
Gracias @PravinDeshmukh pero eso devuelve el nombre del usuario y no la identificación
MRainzo
1
Deberia de funcionar. Vea las muestras en asp.net github.com/aspnet/Identity/blob/… . Solo asegúrese de que el usuario haya iniciado sesión. @PravinDeshmukh, nunca use System.Web.HttpContext.Current en vnext :)
user960567
1
Hola @ user960567, ¿puedes decirnos por qué?
Pravin Deshmukh
@PravinDeshmukh porque no funcionará en .NET core y no hay dependencia de System.Web.
user960567

Respuestas:

148

Actualización en ASP.NET Core Version> = 2.0

En el controlador:

public class YourControllerNameController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;

    public YourControllerNameController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task<IActionResult> YourMethodName()
    {
        var userId =  User.FindFirstValue(ClaimTypes.NameIdentifier) // will give the user's userId
        var userName =  User.FindFirstValue(ClaimTypes.Name) // will give the user's userName

        ApplicationUser applicationUser = await _userManager.GetUserAsync(User);
        string userEmail = applicationUser?.Email; // will give the user's Email
    }
}

En alguna otra clase:

public class OtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public OtherClass(IHttpContextAccessor httpContextAccessor)
    {
       _httpContextAccessor = httpContextAccessor;
    }

   public void YourMethodName()
   {
      var userId = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
   }
}

Entonces debe registrarse IHttpContextAccessoren la Startupclase de la siguiente manera:

public void ConfigureServices(IServiceCollection services)
{
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

Para mayor legibilidad, escriba los métodos de extensión de la siguiente manera:

public static class ClaimsPrincipalExtensions
{
    public static T GetLoggedInUserId<T>(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier);

        if (typeof(T) == typeof(string))
        {
            return (T)Convert.ChangeType(loggedInUserId, typeof(T));
        }
        else if (typeof(T) == typeof(int) || typeof(T) == typeof(long))
        {
            return loggedInUserId != null ? (T)Convert.ChangeType(loggedInUserId, typeof(T)) : (T)Convert.ChangeType(0, typeof(T));
        }
        else
        {
            throw new Exception("Invalid type provided");
        }
    }

    public static string GetLoggedInUserName(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        return principal.FindFirstValue(ClaimTypes.Name);
    }

    public static string GetLoggedInUserEmail(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        return principal.FindFirstValue(ClaimTypes.Email);
    }
}

Luego use de la siguiente manera:

public class YourControllerNameController : Controller
{
    public IActionResult YourMethodName()
    {
        var userId = User.GetLoggedInUserId<string>(); // Specify the type of your UserId;
        var userName = User.GetLoggedInUserName();
        var userEmail = User.GetLoggedInUserEmail();
    }
}

public class OtherClass
{
     private readonly IHttpContextAccessor _httpContextAccessor;
     public OtherClass(IHttpContextAccessor httpContextAccessor)
     {
         _httpContextAccessor = httpContextAccessor;
     }

     public void YourMethodName()
     {
         var userId = _httpContextAccessor.HttpContext.User.GetLoggedInUserId<string>(); // Specify the type of your UserId;
     }
}
TanvirArjel
fuente
1
¿Pero el usuario devuelve nulo en mi caso? ¿Dónde estoy haciendo mal?
Sruthi Varghese
¿Estás seguro de haber iniciado sesión con un usuario?
TanvirArjel
Mi escenario es como si quisiera el nombre de usuario del usuario registrado en mi sistema. ¿Dejar que sea Ubuntu o Windows? Y como estoy probando esto en Windows, inicié sesión con mi nombre. Pero está volviendo null.
Sruthi Varghese
¡Entonces tienes que ver tu código! Puede ser cualquier agente externo que juegue un papel aquí.
TanvirArjel
2
Descubrí que si tiene un resultado nulo User.Identity.Name, podría deberse a que la autenticación anónima está habilitada. Pude User.Identity.Namedevolver mi dominio y nombre de usuario expandiéndome Properties > launchSettings.jsony configurándome anonymousAuthenticationen falsey windowsAuthenticationpara true.
Andrew Gray
109

Hasta ASP.NET Core 1.0 RC1 :

Es User.GetUserId () del espacio de nombres System.Security.Claims .

Desde ASP.NET Core 1.0 RC2 :

Ahora tiene que usar UserManager . Puede crear un método para obtener el usuario actual:

private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);

Y obtenga información del usuario con el objeto:

var user = await GetCurrentUserAsync();

var userId = user?.Id;
string mail = user?.Email;

Nota: Puede hacerlo sin usar un método que escriba líneas individuales como esta string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Email, pero no respeta el principio de responsabilidad única. Es mejor aislar la forma en que obtiene al usuario porque si algún día decide cambiar su sistema de administración de usuarios, como usar otra solución que no sea Identity, se volverá doloroso ya que debe revisar todo el código.

AdrienTorris
fuente
1
Tengo el espacio de nombres System.Security.Claims y el ensamblado Microsoft.AspNet.Identity.
scottheckel
2
Creo que esta respuesta es mejor que la respuesta aceptada, especialmente porque asp.net core está promoviendo la inyección de dependencia.
Phillip Davis el
2
Parece incorrecto porque userManager hará una solicitud a la base de datos para recuperar información sobre el usuario. Y en este caso, el ID de usuario ya estaba disponible en HttpContext.User
incógnito
@incognito El identificador fue solo un ejemplo, pero puede obtener toda la información que necesita con el objeto del usuario
AdrienTorris
2
@Adrien, pero la pregunta era cómo obtener la identificación de usuario. Solo quería decir que la forma proporcionada no es la más eficiente. Para este caso, preferiría la respuesta de Soren o la versión más corta que se puede encontrar en los comentarios.
incógnito
91

puedes obtenerlo en tu controlador:

using System.Security.Claims;
var userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

o escriba un método de extensión como antes .Core v1.0

using System;
using System.Security.Claims;

namespace Shared.Web.MvcExtensions
{
    public static class ClaimsPrincipalExtensions
    {
        public static string GetUserId(this ClaimsPrincipal principal)
        {
            if (principal == null)
                throw new ArgumentNullException(nameof(principal));

            return principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        }
    }
}

y llegar a donde esté disponible el usuario ClaimsPrincipal :

using Microsoft.AspNetCore.Mvc;
using Shared.Web.MvcExtensions;

namespace Web.Site.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return Content(this.User.GetUserId());
        }
    }
}
Soren
fuente
16
Versión más corta:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
CFreitas
1
Tenga en cuenta que este método de extensión solo funciona para el usuario dentro de los controladores, no para ver los componentes, ya que el componente de vista Usuario es de IPrincipal
adam3039
@AK que puede usar Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))para obtener un UserId entero
Hamza Khanzada
1
@HamzaKhanzada Sí, funciona, pero se ve tan largo y feo.
AK
39

Incluí el uso de System.Security.Claims y pude acceder al método de extensión GetUserId ()

NB: ya tenía Microsoft.AspNet.Identity usando pero no pude obtener el método de extensión. Supongo que ambos deben usarse en conjunto

using Microsoft.AspNet.Identity;
using System.Security.Claims;

EDITAR : Esta respuesta ahora está desactualizada. Mire la respuesta de Soren o Adrien para obtener una forma anticuada de lograr esto en CORE 1.0

MRainzo
fuente
17
Esta fue la salsa secreta, pero para cualquiera que esté buscando después de agregar estos usos, es ... var userId = User.GetUserId();
Samurai Ken
44
la extensión .GetUserId () de ClaimsPrincipal (Controller.User) se ha movido a => UserManager.GetUserId (Usuario);
Soren
1
usando System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
Cambie el
3
Pulgares arriba para obtener una respuesta previamente válida e identificar correctamente la nueva respuesta "correcta".
pimbrouwers
26

Solo para .NET Core 2.0 Se requiere lo siguiente para obtener el ID de usuario del usuario conectado en una Controllerclase:

var userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

o

var userId = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);

p.ej

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);
Hombre oracular
fuente
17

Como se indicó en alguna parte de esta publicación, el método GetUserId () se ha movido al UserManager.

private readonly UserManager<ApplicationUser> _userManager;

public YourController(UserManager<ApplicationUser> userManager)
{
    _userManager = userManager;
}

public IActionResult MyAction()
{
    var userId = _userManager.GetUserId(HttpContext.User);

    var model = GetSomeModelByUserId(userId);

    return View(model);
}

Si comenzó un proyecto vacío, es posible que deba agregar el UserManger a sus servicios en startup.cs. De lo contrario, este ya debería ser el caso.

Menno Guldemond
fuente
10

debes importar Microsoft.AspNetCore.Identity & System.Security.Claims

// to get current user ID
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

// to get current user info
var user = await _userManager.FindByIdAsync(userId);
Mansur Haider
fuente
de todas estas respuestas, la suya es la única que funciona con ASP.NET CORE v 2.0. Congratz!
Just Fair
eso es todo. Cualquiera de .NET Core 2.0 y superior, esta es su respuesta
alvinchesaro
1
Probado en .NET Core 3.1 en una configuración Web API + JWT. Quiero que el usuario con sesión iniciada actualmente en un controlador base, esto no es eficiente, consultar al usuario desde la base de datos para cada solicitud, etc. ¿Hay alguna forma de obtener el usuario actual sin consultar la base de datos?
Nexus
¿por qué la mía volver "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"a User.FindFirstValue(ClaimTypes.NameIdentifier);?
pueril
5

Aunque la respuesta de Adrien es correcta, puede hacer todo esto en una sola línea. No hay necesidad de funciones adicionales o desorden.

Funciona, lo comprobé en ASP.NET Core 1.0

var user = await _userManager.GetUserAsync(HttpContext.User);

entonces puede obtener otras propiedades de la variable como user.Email. Espero que esto ayude a alguien.

Ahmad
fuente
3
La razón por la que estoy usando un método es para respetar el principio de responsabilidad única. Si no aísla la forma en que obtiene al usuario, será doloroso si algún día decide modificar su sistema de administración de usuarios, como usar otra solución que no sea Identity.
AdrienTorris
5

Para ASP.NET Core 2.0, Entity Framework Core 2.0, AspNetCore.Identity 2.0 api ( https://github.com/kkagill/ContosoUniversity-Backend ):

El Idfue cambiado aUser.Identity.Name

    [Authorize, HttpGet("Profile")]
    public async Task<IActionResult> GetProfile()
    {
        var user = await _userManager.FindByIdAsync(User.Identity.Name);

        return Json(new
        {
            IsAuthenticated = User.Identity.IsAuthenticated,
            Id = User.Identity.Name,
            Name = $"{user.FirstName} {user.LastName}",
            Type = User.Identity.AuthenticationType,
        });
    }

Respuesta:

ingrese la descripción de la imagen aquí

jv_
fuente
Sin this.User.Identity.Nameembargo , según mi prueba, tiende a ser el nombre de usuario. En mi prueba, el nombre de usuario es un correo electrónico, ya sea que el usuario inicie sesión desde el registro o inicie sesión desde un inicio de sesión externo (por ejemplo, Facebook, Google). El siguiente código devuelve el ID de usuario. Utilizo una clave primaria de incremento automático para mi tabla de usuario de identidad, de ahí el int.Parse. int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
Michael Buen
1
FindByIdAsyncno funciona ya que está proporcionando un nombre de usuario. Funciona cuando lo reemplazas por FindByNameAsync.
Jasper
4

en el APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

Algo como esto obtendrá los reclamos

Usman
fuente
1

User.Identity.GetUserId ();

no existe en asp.net identity core 2.0. En este sentido, me las he arreglado de manera diferente. He creado una clase común para usar toda la aplicación, debido a la obtención de información del usuario.

crear una clase común PCommon e interfaz IPCommon agregando referenciausing System.Security.Claims

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Common.Web.Helper
{
    public class PCommon: IPCommon
    {
        private readonly IHttpContextAccessor _context;
        public PayraCommon(IHttpContextAccessor context)
        {
            _context = context;
        }
        public int GetUserId()
        {
            return Convert.ToInt16(_context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier));
        }
        public string GetUserName()
        {
            return _context.HttpContext.User.Identity.Name;
        }

    }
    public interface IPCommon
    {
        int GetUserId();
        string GetUserName();        
    }    
}

Aquí la implementación de la clase común

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Pay.DataManager.Concreate;
using Pay.DataManager.Helper;
using Pay.DataManager.Models;
using Pay.Web.Helper;
using Pay.Web.Models.GeneralViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Pay.Controllers
{

    [Authorize]
    public class BankController : Controller
    {

        private readonly IUnitOfWork _unitOfWork;
        private readonly ILogger _logger;
        private readonly IPCommon _iPCommon;


        public BankController(IUnitOfWork unitOfWork, IPCommon IPCommon, ILogger logger = null)
        {
            _unitOfWork = unitOfWork;
            _iPCommon = IPCommon;
            if (logger != null) { _logger = logger; }
        }


        public ActionResult Create()
        {
            BankViewModel _bank = new BankViewModel();
            CountryLoad(_bank);
            return View();
        }

        [HttpPost, ActionName("Create")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Insert(BankViewModel bankVM)
        {

            if (!ModelState.IsValid)
            {
                CountryLoad(bankVM);
                //TempData["show-message"] = Notification.Show(CommonMessage.RequiredFieldError("bank"), "Warning", type: ToastType.Warning);
                return View(bankVM);
            }


            try
            {
                bankVM.EntryBy = _iPCommon.GetUserId();
                var userName = _iPCommon.GetUserName()();
                //_unitOfWork.BankRepo.Add(ModelAdapter.ModelMap(new Bank(), bankVM));
                //_unitOfWork.Save();
               // TempData["show-message"] = Notification.Show(CommonMessage.SaveMessage(), "Success", type: ToastType.Success);
            }
            catch (Exception ex)
            {
               // TempData["show-message"] = Notification.Show(CommonMessage.SaveErrorMessage("bank"), "Error", type: ToastType.Error);
            }
            return RedirectToAction(nameof(Index));
        }



    }
}

obtener userId y name en la acción de inserción

_iPCommon.GetUserId();

Gracias Maksud

Maksud
fuente
1
¿Tiene que registrar IHttpContextAccessor en Startup.cs?
REMESQ
1
No REMESQ, no inyecté esto en el inicio, pero estoy trabajando en mi aplicación
Maksud
1

Para obtener la identificación de usuario actual en las vistas de afeitar, podemos inyectar UserManager en la vista de esta manera:

@inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> _userManager
@{ string userId = _userManager.GetUserId(User); }

Espero que le sea útil.

HO3EiN
fuente
0

uso puede usar

string userid = User.FindFirst("id").Value;

por alguna razón, NameIdentifier ahora recupera el nombre de usuario (.net core 2.2)

Mosta
fuente
0

Como administrador que trabaja en el perfil de otras personas y necesita obtener el Id. Del perfil en el que está trabajando, puede usar una ViewBag para capturar el Id, por ejemplo, ViewBag.UserId = userId; mientras userId es el parámetro de cadena del método en el que está trabajando.

    [HttpGet]

    public async Task<IActionResult> ManageUserRoles(string userId)
    {

          ViewBag.UserId = userId;


        var user = await userManager.FindByIdAsync(userId);

        if (user == null)
        {
            ViewBag.ErrorMessage = $"User with Id = {userId} cannot be found";
            return View("NotFound");
        }

        var model = new List<UserRolesViewModel>();

        foreach (var role in roleManager.Roles)
        {
            var userRolesViewModel = new UserRolesViewModel
            {
                RoleId = role.Id,
                RoleName = role.Name
            };

            if (await userManager.IsInRoleAsync(user, role.Name))
            {
                userRolesViewModel.IsSelected = true;
            }
            else
            {
                userRolesViewModel.IsSelected = false;
            }

            model.Add(userRolesViewModel);
        }
        return View(model);
    }
sammy Akinsoju
fuente
-11

Si desea esto en ASP.NET MVC Controller, use

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

Necesita agregar una usingdeclaración porque GetUserId()no estará allí sin ella.

Pravin Deshmukh
fuente
2
Sí, incluí en la pregunta que tengo el "uso de Microsoft.AspNet.Identity". Sin embargo, descubrí cómo resolverlo con mi respuesta en la publicación
MRainzo
1
FWIW es (ahora) User.GetUserId()y noUser.Identity.GetUserId()
lc.
18
La pregunta era y es abou asp.net CORE que tiene el espacio de nombres Microsoft.AspNetCore.Identity; y NO Microsoft.AspNet.Identity; Y usando ese nuevo espacio de nombres, NO hay un método de extensión GetUserId (). ¡ESTA RESPUESTA ES INCORRECTA!
Pascal
44
Fácil en TODAS LAS MAYÚSCULAS. Y aprende sobre ser amable en SO. stackoverflow.blog/2018/04/26/…
smoore4