web-dev-qa-db-fra.com

Identité de base ASP.NET - Obtenir l'utilisateur actuel

Pour obtenir l'utilisateur actuellement connecté dans MVC5, il nous suffisait de:

using Microsoft.AspNet.Identity;
[Authorize]
public IHttpActionResult DoSomething() {
    string currentUserId = User.Identity.GetUserId();
}

Maintenant, avec ASP.NET Core, je pensais que cela devrait fonctionner, mais cela jetterait une erreur.

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Http;

private readonly UserManager<ApplicationUser> _userManager;
[HttpPost]
[Authorize]
public async Task<IActionResult> StartSession() {
    var curUser = await _userManager.GetUserAsync(HttpContext.User);
}

Des idées?

EDIT: La réponse de Gerardo est sur la bonne voie, mais pour obtenir le "Id" réel de l'utilisateur, cela semble fonctionner:

ClaimsPrincipal currentUser = this.User;
var currentUserID = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
56
jbraun

En supposant que votre code se trouve dans un contrôleur MVC:

public class MyController : Microsoft.AspNetCore.Mvc.Controller

À partir de la classe de base Controller, vous pouvez obtenir le IClaimsPrincipal à partir de la propriété User.

System.Security.Claims.ClaimsPrincipal currentUser = this.User;

Vous pouvez vérifier les réclamations directement (sans aller-retour à la base de données):

bool IsAdmin = currentUser.IsInRole("Admin");
var id = _userManager.GetUserId(User); // Get user id:

D'autres champs peuvent être extraits de l'entité utilisateur de la base de données:

  1. Obtenir le gestionnaire d'utilisateurs utilisant l'injection de dépendance

    private UserManager<ApplicationUser> _userManager;
    
    //class constructor
    public MyController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }
    
  2. Et utilisez-le:

    var user = await _userManager.GetUserAsync(User);
    var email = user.Email;
    
92
Gerardo Grignoli

Si vous utilisez Bearing Token Auth, les exemples ci-dessus ne renvoient pas d'utilisateur utilisateur.

Au lieu de cela, utilisez ceci:

ClaimsPrincipal currentUser = this.User;
var currentUserName = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
ApplicationUser user = await _userManager.FindByNameAsync(currentUserName);

Cela fonctionne dans apsnetcore 2.0. Je n'ai pas essayé dans les versions précédentes.

18
Greg Gum

Pour le contexte, j'ai créé un projet à l'aide du modèle d'application Web ASP.NET Core 2. Ensuite, sélectionnez l'application Web (MVC), puis cliquez sur le bouton Modifier l'authentification et sélectionnez Comptes d'utilisateur individuels.

Ce modèle contient de nombreuses infrastructures. Trouvez le ManageController dans le dossier Controllers.

Ce constructeur de classe ManageController nécessite que cette variable UserManager soit renseignée:

private readonly UserManager<ApplicationUser> _userManager;

Ensuite, jetez un coup d'œil à la méthode [HttpPost] Index de cette classe. Ils obtiennent l'utilisateur actuel de cette manière:

var user = await _userManager.GetUserAsync(User);

En prime, vous souhaitez mettre à jour les champs personnalisés du profil utilisateur que vous avez ajouté à la table AspNetUsers. Ajoutez les champs à la vue, puis soumettez ces valeurs à IndexViewModel, qui est ensuite soumis à cette méthode Post. J'ai ajouté ce code après la logique par défaut pour définir l'adresse électronique et le numéro de téléphone:

user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Address1 = model.Address1;
user.Address2 = model.Address2;
user.City = model.City;
user.State = model.State;
user.Zip = model.Zip;
user.Company = model.Company;
user.Country = model.Country;
user.SetDisplayName();
user.SetProfileID();

_dbContext.Attach(user).State = EntityState.Modified;
_dbContext.SaveChanges();
6
Joel Palmer

Dans .NET Core 2.0, l'utilisateur existe déjà dans le cadre du contrôleur hérité sous-jacent. Utilisez simplement l'utilisateur comme vous le feriez normalement ou transmettez-le à n'importe quel code de référentiel.

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Policy = "TENANT")]
[HttpGet("issue-type-selection"), Produces("application/json")]
public async Task<IActionResult> IssueTypeSelection()
{
    try
    {
        return new ObjectResult(await _item.IssueTypeSelection(User));
    }
    catch (ExceptionNotFound)
    {
        Response.StatusCode = (int)HttpStatusCode.BadRequest;
        return Json(new
        {
            error = "invalid_grant",
            error_description = "Item Not Found"
        });
    }
}

C'est de là qu'il hérite

#region Assembly Microsoft.AspNetCore.Mvc.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// C:\Users\BhailDa\.nuget\packages\Microsoft.aspnetcore.mvc.core\2.0.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll
#endregion

using System;
using System.IO;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Routing;
using Microsoft.Net.Http.Headers;

namespace Microsoft.AspNetCore.Mvc
{
    //
    // Summary:
    //     A base class for an MVC controller without view support.
    [Controller]
    public abstract class ControllerBase
    {
        protected ControllerBase();

        //
        // Summary:
        //     Gets the System.Security.Claims.ClaimsPrincipal for user associated with the
        //     executing action.
        public ClaimsPrincipal User { get; }
5
Bhail

Juste si quelqu'un est intéressé, cela a fonctionné pour moi. J'ai une identité personnalisée qui utilise int pour une clé primaire et j'ai donc remplacé la méthode GetUserAsync

Remplacer GetUserAsync

public override Task<User> GetUserAsync(ClaimsPrincipal principal)
{
    var userId = GetUserId(principal);
    return FindByNameAsync(userId);
}

Obtenir un utilisateur d'identité

var user = await _userManager.GetUserAsync(User);

Si vous utilisez une clé primaire Guid standard, vous n'avez pas besoin de remplacer GetUserAsync. Tout cela en supposant que votre jeton est configuré correctement.

public async Task<string> GenerateTokenAsync(string email)
{
    var user = await _userManager.FindByEmailAsync(email);
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_tokenProviderOptions.SecretKey);

    var userRoles = await _userManager.GetRolesAsync(user);
    var roles = userRoles.Select(o => new Claim(ClaimTypes.Role, o));

    var claims = new[]
    {
        new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
        new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString(CultureInfo.CurrentCulture)),
        new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName),
        new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
        new Claim(JwtRegisteredClaimNames.Email, user.Email),
    }
    .Union(roles);

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(claims),
        Expires = DateTime.UtcNow.AddHours(_tokenProviderOptions.Expires),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);

    return Task.FromResult(new JwtSecurityTokenHandler().WriteToken(token)).Result;
}
0
Dblock247

J'ai mis quelque chose comme ça dans ma classe de contrôleur et cela a fonctionné:

IdentityUser user = await userManager.FindByNameAsync(HttpContext.User.Identity.Name);

où userManager est une instance de la classe Microsoft.AspNetCore.Identity.UserManager (avec toute la configuration étrange qui va avec).

0
Marko