web-dev-qa-db-fra.com

Identité ASP.NET (OWIN): Comment obtenir l'ID utilisateur à partir d'un contrôleur API Web?

(Utilisation de VS2013 RTW, ASP.NET MVC5)

J'ai vu beaucoup de documentation sur la façon d'ajouter des propriétés à la classe ApplicationUser (et à la table) lors de l'utilisation de l'identité ASP.NET. Mais je n'ai pas vu de documentation sur la manière de créer une table séparée avec un contenu mappé sur la table ApplicationUser via une clé étrangère.

J'ai dérivé avec succès ma propre table Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext, et maintenant ma propre table "UserPreferences" coexiste en harmonie avec les différentes tables "AspNet *" de ma base de données SQL Server. Mais je ne suis pas sûr de la meilleure façon d'obtenir l'ID de l'utilisateur actuel afin d'écrire une nouvelle ligne dans la table "UserPreferences". Notez que le projet est ASP.NET MVC, mais j'ai ajouté (et travaille à l'intérieur de) un contrôleur API Web.

J'ai une solution de travail qui est:

            var uman = new Microsoft.AspNet.Identity.UserManager<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>(new Microsoft.AspNet.Identity.EntityFramework.UserStore<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>(new App1.Data.App1DbContext()));

            var uident = User.Identity;

            var userobject = uman.FindByNameAsync(uident.Name);

            var userid = userobject.Result.Id;
            // (Perform new row creation including the userid we just looked up

Considérez que la table AspNetUsers (telle que définie par le framework Identity) est composée de ces champs:

-id (PK, nvarchar(128) - seems to contain a GUID, not sure why not an autoincrement integer, but I assume there are reasons for this)
-Username (nvarchar(max))
-PasswordHash (nvarchar(max))
-SecurityStamp (nvarchar(max))

Je pense que le champ id (pas le nom d'utilisateur) est le champ correct à référencer dans ce tableau. (Je pensais qu'un utilisateur pourrait changer son nom d'utilisateur, et quelqu'un d'autre pourrait alors assumer le nom d'utilisateur de l'autre utilisateur, ce qui explique pourquoi les deux champs sont probablement là.) J'ai donc besoin d'obtenir l'ID de l'utilisateur actuel pour le stockage dans "UserPreferences" table, qui est ce que le code ci-dessus fait. Mais il semble inefficace de devoir faire cette recherche.

Un point important est que, dans le contexte d'un System.Web.Mvc.Controller, je peux faire:

User.Identity.GetUserId()
(Runtime type of User.Identity: System.Security.Principal.GenericIdentity)

Mais dans le contexte d'un System.Web.Http.ApiController (API Web), je ne peux pas car cette méthode n'existe pas (type d'exécution de User.Identity: System.Security.Claims.ClaimsIdentity), raison pour laquelle je dois me fier à la place :

User.Identity.Name

et faites la recherche supplémentaire pour convertir Nom en ID. Quelqu'un a-t-il des suggestions pour améliorer cela? Est-ce que j'aborde la tâche d'écrire les données utilisateur dans des tables séparées de la bonne manière?

44
BenjiFB

Vous devriez pouvoir obtenir l'ID utilisateur sur le contrôleur MVC et le contrôleur API Web par la même méthode d'extension dans paquet d'identité 1.0 RTW .

Voici les extensions du paquet d'identité:

namespace Microsoft.AspNet.Identity
{
    public static class IdentityExtensions
    {
        public static string FindFirstValue(this ClaimsIdentity identity, string claimType);
        public static string GetUserId(this IIdentity identity);
        public static string GetUserName(this IIdentity identity);
    }
}

IIdentity est l'interface de base pour tous les types d'identité. Vous devrez peut-être ajouter "à l'aide de Microsoft.AspNet.Identity" pour voir la méthode d'extension.

BTW: en ce qui concerne l'ajout d'une table étrangère pour un utilisateur, pourquoi ne pas utiliser ApplicationUser et ajouter une propriété de navigation à UserPreference pour permettre à EF de gérer leur relation? Ce sera plus facile.

58
Hongye Sun
ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, UserID));

ClaimTypes.NameIdentifier Est la revendication de la fonction User.Identity.GetUserId()

45
Oswaldo Alvarez

J'utilise l'approche basée sur les revendications:

private ApplicationUser GetCurrentUser(ApplicationDbContext context)
{
  var identity = User.Identity as ClaimsIdentity;
  Claim identityClaim = identity.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);

  return context.Users.FirstOrDefault(u => u.Id == identityClaim.Value);
}
12
Mastenka

Brève description pour la meilleure réponse:

  1. Install-Package Microsoft.AspNet.Identity.Core -Version 2.2.1
  2. var userId = User.Identity.GetUserId();
3
neustart47

Essayé @Mastenka répondre et cela ne m'a rien donné. J'ai vérifié ClaimsIdentity et il y avait des revendications de type "UserName". Par conséquent, je reçois un nom d'utilisateur en utilisant "UserName" en tant que ClaimsType. J'espère que quelqu'un donnera plus d'informations à ce sujet. Il semble étrange que "ClaimTypes.NameIdentifier" n'ait eu aucun effet. (ApiController, ASP API MVC)

var userName = ((ClaimsIdentity)RequestContext.Principal.Identity).Claims.FirstOrDefault(cl => cl.Type == "UserName")?.Value;
0
IHAFURR