Obtenga el usuario actual, dentro de una acción ApiController, sin pasar el ID de usuario como parámetro

97

¿Cómo obtenemos el usuario actual, dentro de una acción segura de ApiController, sin pasar el nombre de usuario o el ID de usuario como parámetro?

Asumimos que esto está disponible, porque estamos dentro de una acción segura. Estar en una acción segura significa que el usuario ya se ha autenticado y la solicitud tiene su token de portador. Dado que WebApi ha autorizado al usuario, puede haber una forma integrada de acceder al userId, sin tener que pasarlo como un parámetro de acción.

Shaun Luttin
fuente
Por favor, vea esta respuesta: stackoverflow.com/a/26453782/3290276 Agregue el reclamo hizo el truco
Gabriela Macias

Respuestas:

149

En WebApi 2 puede usar RequestContext.Principaldesde un método en ApiController

Darrel Miller
fuente
1
Parece que no tenemos esa propiedad. Hmm. Quizás estemos usando una versión antigua de WebApi.
Shaun Luttin
2
@ShaunLuttin Ok, entonces si estás usando Web API 1, entonces creo que hay una propiedad de Prinicpal en ApiController. Este es solo un envoltorio elegante para acceder a la colección Request.Properties. El objeto principal se almacena en ese diccionario.
Darrel Miller
6
No lo olvidesusing Microsoft.AspNet.Identity;
Overlord
1
@DarrelMiller ¿hay alguna manera de obtener lo mismo (por ejemplo, contexto de solicitud) de otras partes del código (no dentro del controlador)?
Ajay Aradhya
2
@AjayAradhya Solo si lo pasas por ahí. Los esfuerzos anteriores en marcos web han demostrado que el uso de propiedades estáticas para acceder al contexto de la solicitud causa todo tipo de problemas arquitectónicos. Es conveniente al principio, pero causa muchísimo dolor a largo plazo.
Darrel Miller
36

También puede acceder al principal utilizando la Userpropiedad en ApiController.

Entonces, las siguientes dos declaraciones son básicamente las mismas:

string id;
id = User.Identity.GetUserId();
id = RequestContext.Principal.Identity.GetUserId();
Patricio
fuente
15
Estoy tratando de usar lo que ha escrito aquí, pero la función GetUserId () siempre devuelve nulo. El usuario está autorizado, estoy pasando un token de portador y ApiController tiene el encabezado [Authorize]
Joshua Ohana
La función GetUserId () devuelve un ID solo si el usuario tiene un reclamo NameIdentifier. Para obtener un ejemplo de cómo resolver esto, consulte la respuesta de Oswaldo aquí: stackoverflow.com/questions/19505526
jramm
14

La pista radica en el controlador de cuenta generado automáticamente Webapi2

Tener esta propiedad con getter definido como

public string UserIdentity
        {
            get
            {
                var user = UserManager.FindByName(User.Identity.Name);
                return user;//user.Email
            }
        }

y para obtener UserManager - En WebApi2 -hace como Romanos (lea como AccountController) haga

public ApplicationUserManager UserManager
        {
            get { return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
        }

Esto debería ser compatible en IIS y en modo de autohost

Karan Bhandari
fuente
7

Ninguna de las sugerencias anteriores funcionó para mí. ¡Lo siguiente hizo!

HttpContext.Current.Request.LogonUserIdentity.Name

Supongo que hay una amplia variedad de escenarios y este funcionó para mí. Mi escenario involucró una interfaz AngularJS y una aplicación de backend Web API 2, ambas ejecutándose bajo IIS. Tuve que configurar ambas aplicaciones para que se ejecutaran exclusivamente bajo la autenticación de Windows.

No es necesario pasar ninguna información de usuario. El navegador y IIS intercambian las credenciales del usuario que ha iniciado sesión y la API web tiene acceso a las credenciales del usuario a pedido (de IIS, supongo).

Kannankeril
fuente
6

La respuesta de Karan Bhandari es buena, pero es muy probable que el AccountController agregado en un proyecto sea un Mvc.Controller. Para convertir su respuesta para su uso en un cambio ApiController HttpContext.Current.GetOwinContext()a Request.GetOwinContext()y asegúrese de que haya añadido los 2 siguientes usingafirmaciones:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
Jeff Leach
fuente
5

En .Net Core, se usa User.Identity.Namepara obtener el reclamo de nombre del usuario.

Venkatesh Muniyandi
fuente
2
User.Identity.Nameobtiene el valor de la reclamación de nombre . No es específico de Active Directory.
Nate Barbettini
@Nate Gracias por tu comentario, lo he arreglado
Venkatesh Muniyandi
3

Si está utilizando Asp.Identity UseManager, establece automáticamente el valor de

RequestContext.Principal.Identity.GetUserId ()

basado en IdentityUser que utiliza para crear IdentityDbContext .

Si alguna vez está implementando una tabla de usuario personalizada y una autenticación de portador de token propio, verifique mi respuesta.

¿Cómo obtener el contexto del usuario durante las llamadas de Web Api?

Espero que todavía ayude. :)

pampi
fuente
1
string userName;
string userId;
if (HttpContext.Current != null && HttpContext.Current.User != null 
        && HttpContext.Current.User.Identity.Name != null)
{
    userName = HttpContext.Current.User.Identity.Name;
    userId = HttpContext.Current.User.Identity.GetUserId();
}

O según el comentario de Darrel Miller, tal vez use esto para recuperar primero el HttpContext.

// get httpContext
object httpContext;
actionContext.Request.Properties.TryGetValue("MS_HttpContext", out httpContext);    

Ver también:

Cómo acceder a HTTPContext desde la acción de su API web

Shaun Luttin
fuente
5
No use HttpContext ya que limita sus opciones de alojamiento y hace que su código sea difícil de probar.
Darrel Miller
El objeto HttpContext no estará en el diccionario si es Self-host o OwinHttpListener alojado
Darrel Miller