web-dev-qa-db-fra.com

Méthode appropriée pour obtenir l'ID utilisateur actuel dans Entity Framework Core

Il y a un tas de réponses différentes flottant ici pour les différents RC de ASP.NET Core sur la façon d'obtenir l'ID de l'utilisateur actuellement connecté. Je voulais poser la question définitive ici. Veuillez noter que project.json a désormais "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0"

Avec RC1, vous pourriez faire quelque chose comme ceci:

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

User.GetUserId();

Mais avec la nouvelle version 1 d'EF Core, Microsoft.AspNet.Identity n'est pas la bonne version.

Il a été suggéré d'utiliser UserManager, ce qui semble beaucoup pour obtenir l'utilisateur actuellement connecté:

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

var user = await GetCurrentUserAsync();
var userId = user?.Id;

Une autre méthode que j'ai trouvée était:

private readonly UserManager<ApplicationUser> _userManager;
_userManager.GetUserId(User)

Donc, avec ASP.NET Core 1 RTM et EF Core 1 avec les bibliothèques suivantes dans project.json, quelle est la bonne façon d'obtenir l'ID de l'utilisateur actuellement connecté?

"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
18
Reza

ASP.NET Core Identity est injecté via DI dans startup.cs - en tant que tel, il vous suffit d'injecter UserManager via un constructeur

UserManager<ApplicationUser> userManager

Vous pouvez ensuite utiliser ce qui suit dans les méthodes

_userManager.GetUserId(User);

C'est la façon dont il est utilisé dans l'exemple d'application Web lorsque vous créez un nouveau projet ASP.NET Core 1 avec un compte d'utilisateur individuel.

14
Reza

Si vous y accédez à partir du contrôleur, l'utilisation de serManager pour obtenir l'ID utilisateur est assez inefficace car vous effectuez un aller-retour vers la base de données. Si vous utilisez ClaimsIdentity, vous pouvez faire quelque chose comme ceci pour obtenir l'ID utilisateur:

var claimsIdentity = (ClaimsIdentity)this.User.Identity;
var claim = claimsIdentity.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
var userId = claim.Value;

Cette méthode lit simplement l'ID utilisateur qui est déjà présent dans le cookie, qui à son tour est automatiquement désérialisé et stocké dans une instance ClaimsIdentity.

J'utilise cette classe d'aide:

public static class UserHelpers
{
    public static string GetUserId(this IPrincipal principal)
    {
        var claimsIdentity = (ClaimsIdentity)principal.Identity;
        var claim = claimsIdentity.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
        return claim.Value;
    }
}

Ainsi, obtenir un ID utilisateur devient:

var userId = this.User.GetUserId();

Si, pour une raison quelconque, la revendication requise n'est pas présente dans la collection Claims, vous pouvez facilement l'ajouter lors de la création de l'utilisateur ClaimsIdentity:

public class ApplicaionUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager)
    {
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        userIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, this.UserId));
        return userIdentity;
    }
}
22
Milos Mrdovic

Le one-liner ci-dessous est une version plus concise des autres réponses ci-dessus.

var user = User.FindFirst(ClaimTypes.NameIdentifier).Value;

Pour expliquer un peu plus loin, je voulais utiliser la forme d'authentification la plus basique sans aucune table dans la base de données, j'ai donc choisi celle-ci - tilisation de l'authentification par cookie sans ASP.NET Core Identity dans la documentation de Core.

Pour que cela fonctionne, la première étape consiste à ajouter les services dans Startup.cs

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
        {
        options.LoginPath = new PathString("/Account/Login/");
        options.LogoutPath = new PathString("/Account/Logoff/");
        options.AccessDeniedPath = new PathString("/Account/AccessDenied/");
        options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
        });

services.ConfigureApplicationCookie(identityOptionsCookies =>
{
    // See https://andrewlock.net/automatically-validating-anti-forgery-tokens-in-asp-net-core-with-the-autovalidateantiforgerytokenattribute/
    identityOptionsCookies.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
});

Ensuite, dans le AccountController sur le message après avoir entré un ID utilisateur et un mot de passe valides, l'authentification basée sur les revendications la plus simple consiste à simplement ajouter l'ID de connexion en tant que revendication, par ex.

var claims = new List {new Claim (ClaimTypes.NameIdentifier, loginViewModel.Guid, ClaimValueTypes.String, issuer),};

            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

            var principal = new ClaimsPrincipal(claimsIdentity);

            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal,
                new AuthenticationProperties
                {
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(_cookieTimeoutInMinutes),
                    IsPersistent = true,
                    AllowRefresh = false
                });

Une fois la connexion terminée, vous pouvez récupérer l'ID utilisateur comme décrit dans la ligne ci-dessus. Voir la réponse de Milos Mrdovic ci-dessus pour les étapes plus détaillées.

var user = User.FindFirst(ClaimTypes.NameIdentifier).Value;

Voir Autorisation basée sur les revendications pour plus d'informations.

2
Andy Creigh

Vous pouvez également obtenir UserId de cette manière.

public class Program
   {
           private readonly SignInManager<ApplicationUser> _signInManager;

           public Program(SignInManager<ApplicationUser> signInManager)
           {
               _signInManager = signInManager;
              var UserId = _signInManager.Context.User.Claims.FirstOrDefault().Value;
           }
   }

Où la classe ApplicationUser est donnée ci-dessous ...

public class ApplicationUser:IdentityUser
    {
        [Column(TypeName = "Nvarchar(500)")]
        public string FirstName { get; set; }
        [Column(TypeName = "Nvarchar(500)")]
        public string MiddleName { get; set; }
        [Column(TypeName = "Nvarchar(500)")]
        public string LastName { get; set; }
        [Column(TypeName = "DateTime")]
        public DateTime? LastAccess { get; set; }
    }

Et votre classe ApplicationUser doit être héritée par IdentityUser.

0
vikas Chaturvedi