Come ottenere l'ID utente attualmente connesso in ASP.NET Core


179

L'ho già fatto prima con MVC5 User.Identity.GetUserId()ma non sembra funzionare qui. Non User.Identityha il GetUserId()metodo

sto usando Microsoft.AspNet.Identity


2
provare questo System.Web.HttpContext.Current.User.Identity.Name?
Pravin Deshmukh,

Grazie @PravinDeshmukh ma questo restituisce il nome dell'utente e non l'id
MRainzo

1
Dovrebbe funzionare. Vedi gli esempi in asp.net github.com/aspnet/Identity/blob/… . Assicurati solo che l'utente abbia effettuato l'accesso. @PravinDeshmukh, non utilizzare mai System.Web.HttpContext.Current in vnext :)
user960567

1
Ciao @ user960567, puoi dirci perché?
Pravin Deshmukh,

@PravinDeshmukh perché non funzionerà su .NET core e non esiste alcuna dipendenza System.Web.
user960567

Risposte:


148

Aggiornamento nella versione ASP.NET Core> = 2.0

Nel controller:

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

In qualche altra 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);
   }
}

Quindi dovresti registrarti IHttpContextAccessornella Startupclasse come segue:

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

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

Per ulteriori leggibilità, scrivere i metodi di estensione come segue:

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

Quindi utilizzare come segue:

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
Ma l'utente sta restituendo null nel mio caso? Dove sto sbagliando?
Sruthi Varghese,

Sei sicuro di aver effettuato l'accesso con un utente?
TanvirArjel,

Il mio scenario è come se volessi che il nome utente dell'utente fosse registrato nel mio sistema. Lascia che sia Ubuntu o Windows? E mentre sto testando questo in Windows ho effettuato l'accesso sotto il mio nome. Ma sta tornando null.
Sruthi Varghese,

Quindi devi vedere il tuo codice! Può essere qualsiasi agente esterno che svolge un ruolo qui.
TanvirArjel,

2
Ho scoperto che se hai ottenuto un risultato nullo User.Identity.Name, potrebbe essere perché l'autenticazione anonima è abilitata. Sono stato in grado di User.Identity.Namerestituire il mio dominio e il mio nome utente espandendo Properties > launchSettings.jsone impostando anonymousAuthenticationsu falsee windowsAuthenticationsu true.
Andrew Gray,

109

Fino a ASP.NET Core 1.0 RC1 :

È User.GetUserId () dallo spazio dei nomi System.Security.Claims .

Da ASP.NET Core 1.0 RC2 :

Ora devi usare UserManager . È possibile creare un metodo per ottenere l'utente corrente:

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

E ottenere informazioni sull'utente con l'oggetto:

var user = await GetCurrentUserAsync();

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

Nota: puoi farlo senza usare un metodo per scrivere singole righe come questa string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Email, ma non rispetta il principio della singola responsabilità. È meglio isolare il modo in cui ottieni l'utente perché se un giorno deciderai di cambiare il tuo sistema di gestione degli utenti, come utilizzare un'altra soluzione rispetto a Identity, diventerà doloroso dal momento che devi rivedere l'intero codice.


1
Ho lo spazio dei nomi System.Security.Claims e l'assembly Microsoft.AspNet.Identity.
scottheckel,

2
Penso che questa risposta sia migliore della risposta accettata soprattutto perché il core asp.net promuove l'iniezione di dipendenza.
Phillip Davis,

2
Sembra sbagliato perché userManager invierà una richiesta al database per recuperare informazioni sull'utente. E in questo caso userId era già disponibile in HttpContext.User
incognito il

@incognito L'identificatore era solo un esempio, ma puoi ottenere tutte le informazioni di cui hai bisogno con l'oggetto dell'utente
AdrienTorris,

2
@Adrien ma la domanda era come ottenere l'ID utente. Volevo solo dire che il modo fornito non è il più efficiente. Per questo caso preferirei la risposta di Soren o la versione più breve che si può trovare nei commenti.
incognito il

91

puoi ottenerlo nel tuo controller:

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

o scrivere un metodo di estensione come prima .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 ottenere ovunque l'utente ClaimsPrincipal sia disponibile :

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
Versione più breve:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
CFreitas,

1
Si noti che questo metodo di estensione funziona solo per l'utente all'interno dei controller, non per visualizzare i componenti, poiché il componente di visualizzazione Utente è di IPrincipal
adam3039

@AK è possibile utilizzare Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))per ottenere UserId intero
Hamza Khanzada

1
@HamzaKhanzada Sì, funziona, ma sembra così lungo e brutto.
AK,

39

Ho incluso utilizzando System.Security.Claims e ho potuto accedere al metodo di estensione GetUserId ()

NB: avevo già utilizzato Microsoft.AspNet.Identity ma non riuscivo a ottenere il metodo di estensione. Quindi immagino che entrambi debbano essere usati insieme

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

EDIT : questa risposta è obsoleta. Guarda la risposta di Soren o Adrien per un modo datato per raggiungere questo obiettivo in CORE 1.0


17
Questa era la salsa segreta, ma per chiunque sia attento dopo aver aggiunto queste usanze è ... var userId = User.GetUserId();
Samurai Ken

4
l'estensione .GetUserId () di ClaimsPrincipal (Controller.User) è stata spostata in => UserManager.GetUserId (Utente);
Soren,

1
utilizzando System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
Cambia il

3
Pollice in su per una risposta precedentemente valida e identificazione corretta della nuova risposta "corretta".
pimbrouwers,

26

Solo per .NET Core 2.0 Per recuperare l'ID utente dell'utente connesso in una Controllerclasse è necessario quanto segue :

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

o

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

per esempio

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

17

Come indicato da qualche parte in questo post, il metodo GetUserId () è stato spostato nel 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 hai avviato un progetto vuoto, potresti dover aggiungere UserManger ai tuoi servizi in startup.cs. Altrimenti questo dovrebbe già essere il caso.


10

devi importare 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);

da tutto questo il tuo è l'unico che funziona con ASP.NET CORE v 2.0. Congratz!
Giusto il

questo è. Qualcuno di .NET Core 2.0 e versioni successive, questa è la tua risposta
alvinchesaro il

1
Testato su .NET Core 3.1 in un'API Web + impostazione JWT. Voglio l'utente attualmente connesso in un controller di base, questo non è efficiente, interroga l'utente dal database per ogni richiesta, ecc. C'è un modo per ottenere l'utente corrente senza interrogare il database?
Nexus

Perché il mio ritorno "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"per User.FindFirstValue(ClaimTypes.NameIdentifier);?
puerile

5

Sebbene la risposta di Adrien sia corretta, puoi farlo tutto in una sola riga. Non c'è bisogno di funzioni extra o disordine.

Funziona L'ho controllato in ASP.NET Core 1.0

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

quindi puoi ottenere altre proprietà della variabile come user.Email. Spero che questo aiuti qualcuno.


3
Il motivo per cui sto usando un metodo è rispettare il principio della responsabilità singola. Se non isola il modo in cui ottieni l'utente, sarà doloroso se un giorno deciderai di modificare il tuo sistema di gestione degli utenti, come utilizzare un'altra soluzione rispetto a Identity.
AdrienTorris,

5

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

È Idstato modificato inUser.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,
        });
    }

Risposta:

inserisci qui la descrizione dell'immagine


Sulla base del mio test, this.User.Identity.Nametende ad essere il nome utente però. Nel mio test, il nome utente è un'e-mail, sia l'utente che accede dalla registrazione o accede da un accesso esterno (ad esempio, Facebook, Google). Il codice seguente restituisce userId. Uso una chiave primaria auto-incrementata per la mia tabella utente di identità, da cui int.Parse. int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
Michael Buen,

1
FindByIdAsyncnon funziona poiché stai fornendo un nome utente. Funziona quando lo si sostituisce con FindByNameAsync.
Jasper,

4

nel APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

Qualcosa del genere otterrai i reclami


1

User.Identity.GetUserId ();

non esiste in asp.net identity core 2.0. a questo proposito, sono riuscito in modo diverso. ho creato una classe comune per utilizzare l'intera applicazione, a causa dell'ottenimento di informazioni sull'utente.

creare un PCommon di classe comune e interfaccia IPCommon aggiungendo riferimentousing 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();        
    }    
}

Qui l'implementazione di classe comune

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



    }
}

ottenere userId e nome nell'azione insert

_iPCommon.GetUserId();

Grazie, Maksud


1
Devi registrare IHttpContextAccessor in Startup.cs?
REMESQ,

1
No REMESQ, non l'ho iniettato all'avvio, ma lavorando nella mia applicazione
Maksud,

1

Per ottenere l'ID utente corrente nelle viste del rasoio, possiamo inserire UserManager nella vista in questo modo:

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

Spero che lo trovi utile.


0

l'uso può usare

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

per qualche ragione NameIdentifier ora recupera il nome utente (.net core 2.2)


0

Come amministratore che lavora sul profilo di altre persone e devi ottenere l'ID del profilo su cui stai lavorando, puoi utilizzare un ViewBag per acquisire l'ID, ad esempio ViewBag.UserId = userId; mentre userId è il parametro stringa del metodo su cui stai lavorando.

    [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

Se lo si desidera nel controller MVC ASP.NET, utilizzare

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

Devi aggiungere una usingdichiarazione perché GetUserId()non ci sarebbe senza di essa.


2
Sì, ho incluso nella domanda che ho "using Microsoft.AspNet.Identity". Ho capito come risolverlo però con la mia risposta sul post
MRainzo

1
FWIW è (ora) User.GetUserId()e nonUser.Identity.GetUserId()
lc.

18
La domanda era ed è su asp.net CORE che ha lo spazio dei nomi Microsoft.AspNetCore.Identity; e NON Microsoft.AspNet.Identity; E usando quel nuovo spazio dei nomi NON esiste alcun metodo di estensione GetUserId (). QUESTA RISPOSTA È SBAGLIATA!
Pascal,

4
Facile su TUTTE LE MAIUSCOLE. E impara ad essere gentile su SO. stackoverflow.blog/2018/04/26/...
smoore4
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.