42

(Utilizzo di VS2013 RTW, ASP.NET MVC5)Identità ASP.NET (OWIN): come ottenere UserID da un controller API Web?

Ho visto molta documentazione su come aggiungere proprietà alla classe ApplicationUser (e tabella) quando si utilizza l'identità di ASP.NET. Ma non ho visto alcuna documentazione su come avere una tabella separata con contenuto che si associa alla tabella ApplicationUser tramite una chiave esterna.

Ho ottenuto con successo il mio Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext e ora la mia tabella "UserPreferences" coesiste in armonia con le varie tabelle "AspNet *" nel mio database SQL Server. Ma non sono chiaro sul modo migliore per ottenere l'ID dell'utente corrente in modo da scrivere una nuova riga nella tabella "UserPreferences". Si noti che il progetto è ASP.NET MVC, ma ho aggiunto (e sto lavorando all'interno di) un controller API Web.

ho una soluzione di lavoro, che è:

  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 

Si consideri che la tabella AspNetUsers (come definito dal framework Identity) è costituito da questi campi:

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

Credo che l'id campo (non il nome utente) è il campo corretto per fare riferimento in questa tabella. (Stavo pensando che un utente può cambiare il suo nome utente, e qualcun altro potrebbe quindi assumere il nome utente dell'altro utente, motivo per cui entrambi i campi ci sono probabilmente.) Quindi, ho bisogno di ottenere l'ID dell'utente corrente per l'archiviazione nel Tabella "UserPreferences", che è ciò che fa il codice precedente. Ma sembra inefficiente dover fare questa ricerca.

Un punto importante è che, nel contesto di una System.Web.Mvc.Controller, che posso fare:

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

Ma nel contesto di una System.Web.Http.ApiController (API Web) , non posso perché questo metodo non esiste (tipo di runtime User.Identity: System.Security.Claims.ClaimsIdentity), che è il motivo per cui devo contare invece su:

User.Identity.Name 

e fare la ricerca in più per convertire il nome di ID. Qualcuno ha qualche suggerimento su come questo può essere migliorato? Mi sto avvicinando al compito di scrivere dati utente per separare le tabelle nel modo corretto?

+1

Nota: Secondo questo post: http://stackoverflow.com/questions/9768872/can-i-access-iidentity-from-web-api "ApiController ha una proprietà Richiesta di digitare System.Net.Http.HttpRequestMessage; questo tiene naturalmente i dettagli sulla richiesta corrente (ha anche un setter per scopi di test unitari). HttpRequestMessage ha un dizionario delle proprietà; troverai il valore della chiave MS_UserPrincipal contiene il tuo oggetto IPrincipal. " Ma" MS_UserPrincipal "non esisteva.Io potevo trovare il principal altrove nel dizionario, ma restituiva lo stesso oggetto di cui sopra che non includeva l'ID ... – BenjiFB

risposta

55

Si dovrebbe essere in grado di ottenere l'ID utente su controller MVC e controller web api con lo stesso metodo di estensione in identity 1.0 RTW package.

Ecco le estensioni dal pacchetto di 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); 
    } 
} 

L'IIdentity è l'interfaccia di base per tutti i tipi di identità. Potrebbe essere necessario aggiungere "using Microsoft.AspNet.Identity" per vedere il metodo di estensione.

BTW: per quanto riguarda l'aggiunta di una tabella esterna per l'utente, perché non utilizzare ApplicationUser e aggiungere proprietà di navigazione a UserPreference per consentire a EF di gestire la propria relazione? Sarà più facile

+1

Grazie Hongye, quel metodo di estensione ha fatto proprio quello che mi serviva! > Perché non usare ApplicationUser e aggiungere la proprietà di navigazione a UserPreference per consentire a EF di gestire la loro relazione? Ciò significa poter navigare dagli utenti a le UserPreferences, giusto? Questa è una buona idea. Lo farò. Inoltre, è una cattiva pratica che sto memorizzando GUID (che sono lunghi) come valori di chiavi esterne? Esempio: 307b5c04-254a-4c56-b2bb-a87185883ae7. Sono in grado di memorizzare solo un valore intero. Ciò richiederà più spazio nel DB. – BenjiFB

+2

Nota che potrebbe essere necessario eseguire il cast per poter utilizzare FindFirstValue: '((ClaimsIdentity) User.Identity) .FindFirstValue (" FirstName ")' ad esempio. – Chris

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

ClaimTypes.NameIdentifier è l'affermazione per la funzione User.Identity.GetUserId()

+3

L'aggiunta di questo reclamo quando si autorizza l'utente abilita l'uso di User.Identity.GetUserId(). Questa è la soluzione più semplice. – erlando

8

sto utilizzando l'approccio di base affermazione:

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

Breve descrizione per la migliore risposta:

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