Comment obtenir l'ID utilisateur actuellement connecté dans ASP.NET Core

179

J'ai déjà fait cela avec MVC5 User.Identity.GetUserId()mais cela ne semble pas fonctionner ici. Le User.Identityn'a pas la GetUserId()méthode

j'utilise Microsoft.AspNet.Identity

MRainzo
la source
2
essayez ça System.Web.HttpContext.Current.User.Identity.Name?
Pravin Deshmukh
Merci @PravinDeshmukh mais cela renvoie le nom de l'utilisateur et non l'identifiant
MRainzo
1
Ça devrait marcher. Voir les exemples sur asp.net github.com/aspnet/Identity/blob/… . Assurez-vous simplement que l'utilisateur est connecté. @PravinDeshmukh, n'utilisez jamais System.Web.HttpContext.Current dans vnext :)
user960567
1
Salut @ user960567, pouvez-vous nous dire pourquoi?
Pravin Deshmukh
@PravinDeshmukh car il ne fonctionnera pas sur .NET core et il n'y a pas de dépendance System.Web.
user960567

Réponses:

148

Mise à jour dans la version ASP.NET Core> = 2.0

Dans le contrôleur:

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

Dans une autre 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);
   }
}

Ensuite, vous devez vous inscrire IHttpContextAccessordans la Startupclasse comme suit:

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

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

Pour plus de lisibilité, écrivez les méthodes d'extension comme suit:

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

Puis utilisez comme suit:

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
la source
1
Mais l'utilisateur renvoie null dans mon cas? Où vais-je mal?
Sruthi Varghese
Êtes-vous sûr d'être connecté avec un utilisateur?
TanvirArjel
Mon scénario est comme je veux le nom d'utilisateur de l'utilisateur connecté à mon système. Que ce soit Ubuntu ou Windows? Et pendant que je teste cela dans Windows, je suis connecté sous mon nom. Mais ça revient null.
Sruthi Varghese
Alors devez voir votre code! Peut-être n'importe quel agent externe jouant un rôle ici.
TanvirArjel
2
J'ai constaté que si vous avez un résultat nul User.Identity.Name, cela peut être dû au fait que l'authentification anonyme est activée. J'ai pu User.Identity.Namerenvoyer mon domaine et mon nom d'utilisateur en développant Properties > launchSettings.jsonet en définissant anonymousAuthenticationsur falseet windowsAuthenticationvers true.
Andrew Gray
109

Jusqu'à ASP.NET Core 1.0 RC1 :

C'est User.GetUserId () de System.Security.Claims espace de noms .

Depuis ASP.NET Core 1.0 RC2 :

Vous devez maintenant utiliser UserManager . Vous pouvez créer une méthode pour obtenir l'utilisateur actuel:

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

Et obtenez des informations utilisateur avec l'objet:

var user = await GetCurrentUserAsync();

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

Remarque: Vous pouvez le faire sans utiliser une méthode écrivant des lignes simples comme celle-ci string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Email, mais cela ne respecte pas le principe de responsabilité unique. Il est préférable d'isoler la façon dont vous obtenez l'utilisateur, car si un jour vous décidez de changer votre système de gestion des utilisateurs, comme utiliser une autre solution que Identity, cela deviendra pénible car vous devrez revoir tout votre code.

AdrienTorris
la source
1
J'ai l'espace de noms System.Security.Claims et l'assembly Microsoft.AspNet.Identity.
scottheckel
2
Je pense que cette réponse est meilleure que la réponse acceptée d'autant plus que asp.net core favorise l'injection de dépendances.
Phillip Davis
2
Cela semble erroné car userManager fera une demande à la base de données afin de récupérer des informations sur l'utilisateur. Et dans ce cas, le userId était déjà disponible dans HttpContext.User
incognito
@incognito L'identifiant n'était qu'un exemple mais vous pouvez obtenir toutes les informations dont vous avez besoin avec l'objet utilisateur
AdrienTorris
2
@Adrien mais la question était de savoir comment obtenir l'ID utilisateur. Je voulais juste dire que le moyen fourni n'est pas le plus efficace. Pour ce cas, je préférerais la réponse de Soren ou la version plus courte qui peut être trouvée dans les commentaires.
incognito
91

vous pouvez l'obtenir dans votre contrôleur:

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

ou écrivez une méthode d'extension comme avant .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;
        }
    }
}

et obtenez partout où l'utilisateur ClaimsPrincipal est disponible :

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
la source
16
Version abrégée:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
CFreitas
1
Notez que cette méthode d'extension ne fonctionne que pour l'utilisateur à l'intérieur des contrôleurs, pas pour les composants d'affichage, car le composant de vue User est d'IPrincipal
adam3039
@AK vous pouvez utiliser Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))pour obtenir l'entier UserId
Hamza Khanzada
1
@HamzaKhanzada Oui, ça marche, mais ça a l'air si long et moche.
AK
39

J'ai inclus l'utilisation de System.Security.Claims et j'ai pu accéder à la méthode d'extension GetUserId ()

NB: J'avais déjà utilisé Microsoft.AspNet.Identity mais je n'ai pas pu obtenir la méthode d'extension. Donc je suppose que les deux doivent être utilisés en conjonction l'un avec l'autre

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

EDIT : Cette réponse est maintenant obsolète. Regardez la réponse de Soren ou d'Adrien pour une façon datée d'y parvenir dans CORE 1.0

MRainzo
la source
17
C'était la sauce secrète, mais pour quiconque cherche après avoir ajouté ces utilisations, c'est ... var userId = User.GetUserId();
Samurai Ken
4
l'extension .GetUserId () de ClaimsPrincipal (Controller.User) a été déplacée vers => UserManager.GetUserId (User);
Soren
1
en utilisant System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
Changez le
3
Bravo pour une réponse précédemment valide et identifiant correctement la nouvelle réponse «correcte».
pimbrouwers
26

Pour .NET Core 2.0 uniquement Les éléments suivants sont requis pour récupérer l'ID utilisateur de l'utilisateur connecté dans une Controllerclasse:

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

ou

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

par exemple

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);
Homme oraculaire
la source
17

Comme indiqué quelque part dans cet article, la méthode GetUserId () a été déplacée vers le 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 vous avez démarré un projet vide, vous devrez peut-être ajouter UserManger à vos services dans startup.cs. Sinon, cela devrait déjà être le cas.

Menno Guldemond
la source
10

vous devez importer 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
la source
de toutes ces réponses, la vôtre est la seule qui fonctionne avec ASP.NET CORE v 2.0. Félicitations!
Just Fair
Ça y est. N'importe qui de .NET Core 2.0 et supérieur,
voici
1
Testé sur .NET Core 3.1 dans un paramètre API Web + JWT. Je veux que l'utilisateur actuellement connecté dans un contrôleur de base, ce n'est pas efficace, interroger l'utilisateur de la base de données pour chaque demande, etc. Existe-t-il un moyen d'obtenir l'utilisateur actuel sans interroger la base de données?
Nexus
pourquoi le mien revient "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"-il User.FindFirstValue(ClaimTypes.NameIdentifier);?
puéril le
5

Bien que la réponse d'Adrien soit correcte, vous pouvez tout faire en une seule ligne. Pas besoin de fonction supplémentaire ou de désordre.

Cela fonctionne je l'ai vérifié dans ASP.NET Core 1.0

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

alors vous pouvez obtenir d'autres propriétés de la variable comme user.Email. J'espère que ça aidera quelqu'un.

Ahmad
la source
3
La raison pour laquelle j'utilise une méthode est de respecter le principe de responsabilité unique. Si vous n'isolez pas la façon dont vous obtenez l'utilisateur, ce sera pénible si un jour vous décidez de modifier votre système de gestion des utilisateurs, comme utiliser une autre solution que Identity.
AdrienTorris
5

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

Le a Idété changé enUser.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,
        });
    }

Réponse:

entrez la description de l'image ici

jv_
la source
Sur la base de mon test, a this.User.Identity.Nametendance à être le nom d'utilisateur. Lors de mon test, le nom d'utilisateur est un e-mail, que l'utilisateur se connecte depuis l'inscription ou se connecte depuis une connexion externe (par exemple, Facebook, Google). Le code suivant renvoie le userId. J'utilise une clé primaire auto-incrémentée pour ma table d'utilisateur d'identité, d'où le int.Parse. int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
Michael Buen
1
FindByIdAsyncne fonctionne pas car vous fournissez un nom d'utilisateur. Cela fonctionne lorsque vous le remplacez par FindByNameAsync.
Jasper
4

dans le APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

Quelque chose comme ça, vous obtiendrez les réclamations

Usman
la source
1

User.Identity.GetUserId ();

n'existe pas dans asp.net identity core 2.0. à cet égard, j'ai géré de manière différente. J'ai créé une classe commune pour toute l'application d'utilisation, en raison de l'obtention d'informations sur l'utilisateur.

créer une classe commune PCommon & interface IPCommon ajoutant une référenceusing 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();        
    }    
}

Voici l'implémentation de la classe commune

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



    }
}

obtenir l'ID utilisateur et le nom dans l'action d'insertion

_iPCommon.GetUserId();

Merci, Maksud

Maksud
la source
1
Devez-vous enregistrer IHttpContextAccessor dans Startup.cs?
REMESQ
1
Pas de REMESQ, je n'ai pas injecté cela dans le démarrage, mais travaillant dans mon application
Maksud
1

Pour obtenir l'ID utilisateur actuel dans les vues rasoir, nous pouvons injecter UserManager dans la vue comme ceci:

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

J'espère que tu trouves cela utile.

HO3EiN
la source
0

l'utilisation peut utiliser

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

pour une raison quelconque, NameIdentifier récupère maintenant le nom d'utilisateur (.net core 2.2)

Mosta
la source
0

En tant qu'administrateur travaillant sur le profil d'autres personnes et que vous devez obtenir l'ID du profil sur lequel vous travaillez, vous pouvez utiliser un ViewBag pour capturer l'ID, par exemple ViewBag.UserId = userId; while userId est la chaîne Paramètre de la méthode sur laquelle vous travaillez.

    [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
la source
-11

Si vous le souhaitez dans ASP.NET MVC Controller, utilisez

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

Vous devez ajouter une usingdéclaration car vous GetUserId()ne serez pas là sans elle.

Pravin Deshmukh
la source
2
Oui, j'ai inclus dans la question que j'ai le "using Microsoft.AspNet.Identity". J'ai trouvé comment le résoudre avec ma réponse sur le post
MRainzo
1
FWIW c'est (maintenant) User.GetUserId()et nonUser.Identity.GetUserId()
lc.
18
La question était et est abou asp.net CORE qui a l'espace de noms Microsoft.AspNetCore.Identity; et PAS Microsoft.AspNet.Identity; Et en utilisant ce nouvel espace de noms, il n'y a PAS de méthode d'extension GetUserId (). CETTE RÉPONSE EST FAUX!
Pascal
4
Facile sur le ALL CAPS. Et apprenez à être gentil sur SO. stackoverflow.blog/2018/04/26/…
smoore4