Jak uzyskać bieżący identyfikator zalogowanego użytkownika w ASP.NET Core


179

Zrobiłem to już wcześniej przy użyciu MVC5, User.Identity.GetUserId()ale wydaje się, że tutaj nie działa. Nie User.Identityma GetUserId()metody

ja używam Microsoft.AspNet.Identity


2
spróbować tego System.Web.HttpContext.Current.User.Identity.Name?
— Pravin Deshmukh

Dziękuję @PravinDeshmukh, ale to zwraca nazwę użytkownika, a nie identyfikator
— MRainzo

1
Powinno działać. Zobacz przykłady w asp.net github.com/aspnet/Identity/blob/… . Tylko upewnij się, że użytkownik jest zalogowany. @PravinDeshmukh, nigdy nie używaj System.Web.HttpContext.Current w vnext :)
— user960567

1
Cześć @ user960567, czy możesz nam powiedzieć, dlaczego?
— Pravin Deshmukh

@PravinDeshmukh, ponieważ nie będzie działać na .NET core i nie ma zależności System.Web.
— user960567

Odpowiedzi:


148

Aktualizacja w wersji ASP.NET Core> = 2,0

W kontrolerze:

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

W innej klasie:

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

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

Następnie należy zarejestrować się IHttpContextAccessorna Startupzajęcia w następujący sposób:

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

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

Aby uzyskać większą czytelność metod rozszerzenia zapisu w następujący sposób:

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

Następnie użyj w następujący sposób:

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

1
Ale w moim przypadku Użytkownik zwraca wartość null? Gdzie ja robię źle?
— Sruthi Varghese,

Czy na pewno jesteś zalogowany jako użytkownik?
— TanvirArjel

Mój scenariusz jest taki, jak chcę, aby nazwa użytkownika zalogowała się do mojego systemu. Niech to będzie Ubuntu czy Windows? A ponieważ testuję to w systemie Windows, jestem zalogowany pod swoim nazwiskiem. Ale wraca null.
— Sruthi Varghese,

Następnie musisz zobaczyć swój kod! Może to być dowolny agent zewnętrzny odgrywający tutaj rolę.
— TanvirArjel

2
Zauważyłem, że jeśli masz wynik zerowy z User.Identity.Name, może to być spowodowane włączeniem uwierzytelniania anonimowego. Mogłem User.Identity.Nameodzyskać moją domenę i nazwę użytkownika, rozwijając Properties > launchSettings.json, ustawiając anonymousAuthenticationna falsei windowsAuthenticationdo true.
— Andrew Gray

109

Do ASP.NET Core 1.0 RC1 :

To User.GetUserId () z przestrzeni nazw System.Security.Claims .

Od ASP.NET Core 1.0 RC2 :

Teraz musisz użyć UserManager . Możesz utworzyć metodę, aby pobrać bieżącego użytkownika:

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

I uzyskaj informacje o użytkowniku z obiektem:

var user = await GetCurrentUserAsync();

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

Uwaga: Możesz to zrobić bez używania metody pisania pojedynczych wierszy, jak ta string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Email, ale nie jest to zgodne z zasadą pojedynczej odpowiedzialności. Lepiej wyodrębnić sposób, w jaki zdobywasz użytkownika, ponieważ jeśli pewnego dnia zdecydujesz się zmienić system zarządzania użytkownikami, na przykład użyć innego rozwiązania niż tożsamość, będzie to bolesne, ponieważ będziesz musiał przejrzeć cały kod.


1
Mam przestrzeń nazw System.Security.Claims i zestaw Microsoft.AspNet.Identity.
— scottheckel,

2
Myślę, że ta odpowiedź jest lepsza niż akceptowana odpowiedź, zwłaszcza że rdzeń asp.net promuje wstrzykiwanie zależności.
— Phillip Davis

2
Wydaje się to niewłaściwe, ponieważ userManager wysyła żądanie do bazy danych w celu pobrania informacji o użytkowniku. I w tym przypadku userId był już dostępny w HttpContext.User
— incognito

@incognito Identyfikator był tylko przykładem, ale wszystkie potrzebne informacje można uzyskać za pomocą obiektu użytkownika
— AdrienTorris

2
@Adrien, ale pytanie brzmiało, jak uzyskać identyfikator użytkownika. Chciałem tylko powiedzieć, że podany sposób nie jest najbardziej wydajny. W tym przypadku wolałbym odpowiedź Sorena lub krótszą wersję, którą można znaleźć w komentarzach.
— incognito

91

możesz go pobrać w swoim kontrolerze:

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

lub napisz metodę rozszerzającą, taką jak poprzednio .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;
        }
    }
}

i uzyskaj wszędzie tam, gdzie jest dostępny User 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());
        }
    }
}

16
Krótsza wersja:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
— CFreitas

1
Zauważ, że ta metoda rozszerzenia działa tylko dla użytkownika wewnątrz kontrolerów, a nie dla komponentów widoku, ponieważ komponent widoku User jest z
— IPrincipal

@AK możesz użyć, Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))aby uzyskać całkowity identyfikator użytkownika
— Hamza Khanzada

1
@HamzaKhanzada Tak, to działa, ale wygląda tak długo i brzydko.
— AK

39

Uwzględniłem użycie System.Security.Claims i mogłem uzyskać dostęp do metody rozszerzenia GetUserId ()

Uwaga: już korzystałem z Microsoft.AspNet.Identity, ale nie mogłem uzyskać metody rozszerzenia. Więc myślę, że oba z nich muszą być używane w połączeniu ze sobą

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

EDYCJA : Ta odpowiedź jest teraz nieaktualna. Spójrz na odpowiedź Sorena lub Adriena, aby znaleźć przestarzały sposób osiągnięcia tego w CORE 1.0


17
To był tajny sos, ale dla każdego, kto spojrzy po dodaniu tych zastosowań, jest ... var userId = User.GetUserId();
— Samurai Ken

4
Rozszerzenie .GetUserId () z ClaimsPrincipal (Controller.User) zostało przeniesione do => UserManager.GetUserId (User);
— Soren

1
using System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
— Przełącz się

3
Kciuki w górę za poprzednio ważną odpowiedź i poprawne zidentyfikowanie nowej „poprawnej” odpowiedzi.
— pimbrouwers,

26

Tylko dla .NET Core 2.0 Poniższe są wymagane do pobrania identyfikatora użytkownika zalogowanego użytkownika w Controllerklasie:

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

lub

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

na przykład

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

17

Jak stwierdzono gdzieś w tym poście, metoda GetUserId () została przeniesiona do 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);
}

Jeśli uruchomiłeś pusty projekt, może być konieczne dodanie Menedżera użytkownika do usług w startup.cs. W przeciwnym razie powinno to już mieć miejsce.


10

musisz zaimportować 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);

z tego wszystkiego wynika, że ​​Twój jest jedynym, który współpracuje z ASP.NET CORE v 2.0. Congratz!
— Just Fair

to jest to. Każdy z .NET Core 2.0 i nowszych, oto twoja odpowiedź
— alvinchesaro,

1
Przetestowano na platformie .NET Core 3.1 w ustawieniu interfejsu API sieci Web + JWT. Chcę, aby aktualnie zalogowany użytkownik znajdował się w kontrolerze podstawowym, nie jest to wydajne, wysyłanie zapytań do użytkownika z bazy danych dla każdego żądania itp. Czy istnieje sposób na uzyskanie bieżącego użytkownika bez wysyłania zapytań do bazy danych?
— Nexus

dlaczego mój wraca "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"po User.FindFirstValue(ClaimTypes.NameIdentifier);?
— dziecinny

5

Chociaż odpowiedź Adriena jest poprawna, możesz to wszystko zrobić w jednej linii. Nie ma potrzeby korzystania z dodatkowej funkcji ani bałaganu.

Działa Sprawdziłem to w ASP.NET Core 1.0

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

wtedy możesz uzyskać inne właściwości zmiennej, takie jak user.Email. Mam nadzieję, że to komuś pomoże.


3
Powodem, dla którego używam metody, jest przestrzeganie zasady pojedynczej odpowiedzialności. Jeśli nie wyodrębnisz sposobu, w jaki zdobywasz użytkownika, będzie to bolesne, jeśli pewnego dnia zdecydujesz się zmodyfikować swój system zarządzania użytkownikami, na przykład użyć innego rozwiązania niż tożsamość.
— AdrienTorris

5

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

IdZostała zmieniona naUser.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,
        });
    }

Odpowiedź:

wprowadź opis obrazu tutaj


this.User.Identity.NameJednak na podstawie mojego testu jest to nazwa użytkownika. W moim teście nazwa użytkownika to e-mail, czy użytkownik loguje się z rejestracji, czy loguje się z zewnętrznego loginu (np. Facebook, Google). Poniższy kod zwraca userId. Używam automatycznie zwiększanego klucza podstawowego dla mojej tabeli użytkowników tożsamości, stąd int.Parse. int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
— Michael Buen

1
FindByIdAsyncnie działa, ponieważ podajesz nazwę użytkownika. Działa, gdy zastąpisz go FindByNameAsync.
— Jasper

4

w APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

Coś takiego otrzymasz roszczenia


1

User.Identity.GetUserId ();

nie istnieje w rdzeniu tożsamości asp.net 2.0. w tym zakresie poradziłem sobie w inny sposób. stworzyłem wspólną klasę do wykorzystania w całej aplikacji, ze względu na uzyskiwanie informacji o użytkowniku.

utwórz wspólną klasę PCommon i interfejs IPCommon, dodając odniesienieusing 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();        
    }    
}

Tutaj implementacja wspólnej klasy

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



    }
}

get userId i name w akcji insert

_iPCommon.GetUserId();

Dzięki, Maksud


1
Czy musisz zarejestrować IHttpContextAccessor w Startup.cs?
— REMESQ

1
Nie REMESQ, nie wstrzyknąłem tego do uruchamiania, ale działam w mojej aplikacji
— Maksud

1

Aby uzyskać bieżący identyfikator użytkownika w widokach maszynki do golenia, możemy wstrzyknąć UserManager w widoku w następujący sposób:

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

Mam nadzieję, że uznasz to za przydatne.


0

używać można użyć

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

z jakiegoś powodu NameIdentifier pobiera teraz nazwę użytkownika (.net core 2.2)


0

Jako administrator pracujący na profilach innych osób i potrzebujesz uzyskać identyfikator profilu, nad którym pracujesz, możesz użyć ViewBag do przechwycenia Id, np. ViewBag.UserId = userId; while userId jest ciągiem parametrów metody, nad którą pracujesz.

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

-11

Jeśli chcesz to w kontrolerze ASP.NET MVC, użyj

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

Musisz dodać usingoświadczenie, ponieważ GetUserId()bez niego nie będzie.


2
Tak, zawarłem w pytaniu, że mam „using Microsoft.AspNet.Identity”. Dowiedziałem się jednak, jak to rozwiązać, dzięki mojej odpowiedzi na poście
— MRainzo,

1
FWIW to (teraz) User.GetUserId()a nieUser.Identity.GetUserId()
— lc.

18
Pytanie brzmiało i jest abou asp.net CORE, który ma przestrzeń nazw Microsoft.AspNetCore.Identity; a NIE Microsoft.AspNet.Identity; Używając tej nowej przestrzeni nazw, NIE MA metody rozszerzenia GetUserId (). TA ODPOWIEDŹ JEST ZŁA!
— Pascal

4
Łatwy na WSZYSTKICH KAPTURACH I dowiedz się, jak być miłym w SO. stackoverflow.blog/2018/04/26/…
— smoore4
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.