Como obter o ID do usuário conectado no ASP.NET Core

179

Eu fiz isso antes com o MVC5 usando, User.Identity.GetUserId()mas isso não parece funcionar aqui. O User.Identitynão tem o GetUserId()método

estou usando Microsoft.AspNet.Identity

MRainzo
fonte
2
tente isso System.Web.HttpContext.Current.User.Identity.Name?
Pravin Deshmukh
Obrigado @PravinDeshmukh mas que retorna o nome do usuário e não o id #
MRainzo 8/15
1
Deveria funcionar. Veja os exemplos em asp.net github.com/aspnet/Identity/blob/… . Apenas verifique se o usuário está logado. @PravinDeshmukh, nunca use System.Web.HttpContext.Current no vnext :)
user960567
1
Olá @ user960567, pode nos dizer por que?
Pravin Deshmukh
@PravinDeshmukh porque não funcionará no núcleo do .NET e não há dependência do System.Web.
precisa saber é o seguinte

Respostas:

148

Atualização na versão principal do ASP.NET> = 2.0

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

Em alguma outra classe:

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

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

Então você deve se registrar IHttpContextAccessorna Startupclasse da seguinte maneira:

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

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

Para mais legibilidade, escreva os métodos de extensão da seguinte maneira:

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

Em seguida, use o seguinte:

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
fonte
1
Mas o usuário está retornando nulo no meu caso? Onde estou fazendo errado?
Sruthi Varghese
Tem certeza de que está logado com um usuário?
TanvirArjel 7/01/19
Meu cenário é como eu quero o nome de usuário do usuário logado no meu sistema. Que seja Ubuntu ou Windows? E enquanto estou testando isso no Windows, estou logado com meu nome. Mas está voltando null.
Sruthi Varghese
Então tem que ver o seu código! Pode ser qualquer agente externo desempenhando um papel aqui.
TanvirArjel 7/01/19
2
Descobri que, se você obteve um resultado nulo User.Identity.Name, pode ser porque a autenticação anônima está ativada. Consegui User.Identity.Nameretornar meu domínio e nome de usuário expandindo Properties > launchSettings.jsone definindo anonymousAuthenticationpara falsee windowsAuthenticationpara true.
Andrew Gray
109

Até o ASP.NET Core 1.0 RC1 :

É User.GetUserId () de System.Security.Claims espaço para nome .

Desde o ASP.NET Core 1.0 RC2 :

Agora você precisa usar o UserManager . Você pode criar um método para obter o usuário atual:

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

E obtenha informações do usuário com o objeto:

var user = await GetCurrentUserAsync();

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

Nota: Você pode fazer isso sem usar um método para escrever linhas únicas como essa string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Email, mas não respeita o princípio de responsabilidade única. É melhor isolar a maneira como você obtém o usuário, porque se algum dia você decidir alterar seu sistema de gerenciamento de usuários, como usar outra solução que não seja a Identity, será doloroso, pois você precisará revisar todo o código.

AdrienTorris
fonte
1
Eu tenho o espaço para nome System.Security.Claims e o assembly Microsoft.AspNet.Identity.
scottheckel
2
Eu acho que essa resposta é melhor que a resposta aceita, especialmente porque o núcleo do asp.net está promovendo a injeção de dependência.
Phillip Davis
2
Parece errado, porque o userManager fará uma solicitação ao banco de dados para recuperar informações sobre o usuário. E, neste caso, o userId já estava disponível no HttpContext.User
incognito
@incognito O identificador foi apenas um exemplo, mas você pode obter todas as informações que você precisa com objeto do usuário
AdrienTorris
2
@ Adrien, mas a questão era como obter o ID do usuário. Só queria dizer que a maneira fornecida não é a mais eficiente. Neste caso, eu preferiria a resposta de Soren ou a versão mais curta, que pode ser encontrada nos comentários.
incognito
91

você pode obtê-lo em seu controlador:

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

ou escreva um método de extensão 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;
        }
    }
}

e obtenha onde o usuário ClaimsPrincipal estiver disponível :

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
fonte
16
Versão mais curta:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
CFreitas
1
Note que este método de extensão só funciona para usuário dentro controladores, não visualizar os componentes, como o componente de vista do usuário é de IPrincipal
adam3039
@AK você pode usar Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))para obter um número inteiro de UserId
Hamza Khanzada
1
@HamzaKhanzada Sim, funciona, mas parece tão longo e feio.
AK
39

Eu incluí o uso de System.Security.Claims e pude acessar o método de extensão GetUserId ()

NB: Eu já usava o Microsoft.AspNet.Identity, mas não conseguia obter o método de extensão. Então eu acho que os dois têm que ser usados ​​em conjunto

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

EDIT : Esta resposta está desatualizada. Veja a resposta de Soren ou Adrien para obter uma maneira datada de conseguir isso no CORE 1.0.

MRainzo
fonte
17
Este foi o segredo, mas para qualquer um lookign depois de adicionar estes usings está ... var userId = User.GetUserId();
Samurai Ken
4
a extensão .GetUserId () de ClaimsPrincipal (Controller.User) foi movida para => UserManager.GetUserId (User);
Soren
1
using System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
Comute
3
Polegares para cima para uma resposta previamente válida e para identificar corretamente a nova resposta "correta".
pimbrouwers 5/09/17
26

Somente para .NET Core 2.0 É necessário o seguinte para buscar o UserID do Usuário conectado em uma Controllerclasse:

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

ou

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

por exemplo

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);
Homem Oracular
fonte
17

Conforme declarado em algum lugar nesta postagem, o método GetUserId () foi movido para o 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);
}

Se você iniciou um projeto vazio, pode ser necessário adicionar o UserManger aos seus serviços em startup.cs. Caso contrário, esse já deve ser o caso.

Menno Guldemond
fonte
10

você precisa 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
fonte
de todas essas respostas, a sua é a única que funciona com o ASP.NET CORE v 2.0. Congratz!
Just Fair
é isso. Qualquer pessoa a partir de .NET Núcleo 2.0 e acima, esta é a sua resposta
alvinchesaro
1
Testado no .NET Core 3.1 em uma configuração de API da Web + JWT. Quero o usuário conectado no momento em um controlador base, isso não é eficiente, consultar o usuário do banco de dados para todas as solicitações, etc. Existe alguma maneira de obter o usuário atual sem consultar o banco de dados?
Nexus
por que o meu volta "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"para User.FindFirstValue(ClaimTypes.NameIdentifier);?
puerile 14/06
5

Embora a resposta de Adrien esteja correta, você pode fazer tudo isso em uma única linha. Não há necessidade de função extra ou bagunça.

Funciona, verifiquei no ASP.NET Core 1.0

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

então você pode obter outras propriedades da variável como user.Email. Espero que isso ajude alguém.

Ahmad
fonte
3
A razão pela qual estou usando um método é respeitar o princípio de responsabilidade única. Se você não isolar a maneira como obtém o usuário, será doloroso se algum dia você decidir modificar seu sistema de gerenciamento de usuários, como usar outra solução que não seja a Identity.
AdrianTorris 18/04
5

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

O Idfoi alterado paraUser.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,
        });
    }

Resposta:

insira a descrição da imagem aqui

jv_
fonte
Com base no meu teste, ele this.User.Identity.Nametende a ser o nome de usuário. No meu teste, o nome de usuário é um email, seja o login do usuário no registro ou o login externo (por exemplo, Facebook, Google). O código a seguir retorna o userId. Eu uso uma chave primária incrementada automaticamente para minha tabela de usuários de identidade, daí o int.Parse. int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
Michael Buen
1
FindByIdAsyncnão funciona como você está fornecendo um nome de usuário. Funciona quando você o substitui FindByNameAsync.
Jasper
4

no APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

Algo assim, você receberá as reivindicações

Usman
fonte
1

User.Identity.GetUserId ();

não existe no asp.net identity core 2.0. a este respeito, eu consegui de maneira diferente. Eu criei uma classe comum para usar todo o aplicativo, devido à obtenção de informações do usuário.

criar uma classe comum PCommon e interface IPCommon adicionando referênciausing 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();        
    }    
}

Aqui a implementação da classe comum

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



    }
}

obter userId e nome na ação de inserção

_iPCommon.GetUserId();

Obrigado, Maksud

Maksud
fonte
1
Você precisa registrar o IHttpContextAccessor no Startup.cs?
REMESQ 18/1018
1
Sem REMESQ, eu não injetar isso em arranque, mas trabalhando no meu aplicativo
Maksud
1

Para obter o ID do usuário atual nas visualizações de navalha, podemos injetar o UserManager na visualização da seguinte maneira:

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

Espero que você ache útil.

HO3EiN
fonte
0

uso pode usar

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

por alguma razão, NameIdentifier agora recupera o nome de usuário (.net core 2.2)

Mosta
fonte
0

Como administrador trabalhando no perfil de outras pessoas e você precisa obter o ID do perfil em que está trabalhando, você pode usar um ViewBag para capturar o ID, por exemplo, ViewBag.UserId = userId; enquanto userId é a string Parameter do método em que você está trabalhando.

    [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
fonte
-11

Se você quiser isso no ASP.NET MVC Controller, use

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

Você precisa adicionar uma usingdeclaração porque GetUserId()não estará lá sem ela.

Pravin Deshmukh
fonte
2
Sim, eu incluí na pergunta que eu tenho o "using Microsoft.AspNet.Identity". Eu descobri como resolvê-lo embora com a minha resposta no post
MRainzo 8/15
1
FWIW é (agora) User.GetUserId()e nãoUser.Identity.GetUserId()
lc.
18
A questão era e é abou asp.net CORE, que possui o namespace Microsoft.AspNetCore.Identity; e NÃO Microsoft.AspNet.Identity; E usando esse novo espaço para nome, não existe o método de extensão GetUserId (). ESTA RESPOSTA ESTÁ ERRADA!
Pascal
4
Fácil em todos os CAPS. E aprenda a ser legal com SO. stackoverflow.blog/2018/04/26/...
smoore4