Quiero obtener un usuario actual para obtener información de un usuario, como un correo electrónico. Pero no puedo hacer eso en asp.net core. Estoy tan confundido. Este es mi código.
HttpContext
Casi es nulo en el constructor del controlador. No es bueno tener un usuario en cada acción. Quiero obtener información del usuario una vez y configurarla en ViewData
;
public DashboardController()
{
var user = HttpContext.User.GetUserId();
}
c#
asp.net-core
asp.net-identity
Mehran Hafizi
fuente
fuente
Respuestas:
EDITAR para constructor
El siguiente código funciona:
Editar para RTM
Debes registrarte
IHttpContextAccessor
:fuente
ClaimTypes.NameIdentifier
da la identificación de usuario actual yClaimTypes.Name
da el nombre de usuario.null
en mi caso?.Net core 2.1 Web api
Aunque estoy usando .Manera simple que funciona y lo comprobé.
entonces puede todas las propiedades de estas variables como
user.Email
. Espero que esto ayude a alguien.Editar :
Es una cosa aparentemente simple pero un poco complicada porque hay diferentes tipos de sistemas de autenticación en ASP.NET Core. Actualizo porque algunas personas están recibiendo
null
.Para la autenticación JWT (probado en ASP.NET Core v3.0.0-preview7):
fuente
Tengo otra forma de obtener el usuario actual en Asp.NET Core, y creo que lo vi en algún lugar aquí, en SO ^^
Ese código va al controlador llamado DemoController. No funcionará sin esperar ambos (no se compilará);)
fuente
Tengo que decir que me sorprendió bastante que HttpContext sea nulo dentro del constructor. Estoy seguro de que es por razones de rendimiento. Han confirmado que el uso
IPrincipal
como se describe a continuación lo inyecta en el constructor. Básicamente está haciendo lo mismo que la respuesta aceptada, pero de una manera más interactiva.Para cualquiera que encuentre esta pregunta y busque una respuesta al genérico "¿Cómo obtener un usuario actual?" puedes acceder
User
directamente desdeController.User
. Pero solo puede hacer esto dentro de los métodos de acción (supongo que los controladores no solo se ejecutan con HttpContexts y por razones de rendimiento).Sin embargo, si lo necesita en el constructor (como lo hizo OP) o necesita crear otros objetos inyectables que necesitan el usuario actual, entonces el siguiente es un mejor enfoque:
Inyecte IPrincipal para obtener el usuario
Primer encuentro
IPrincipal
yIIdentity
IPrincipal
yIIdentity
representa al usuario y nombre de usuario. Wikipedia te consolará si 'Principal' suena extraño .Es importante darse cuenta de que si la recibe de
IHttpContextAccessor.HttpContext.User
,ControllerBase.User
oControllerBase.HttpContext.User
que está recibiendo un objeto que se garantiza que sea unClaimsPrincipal
objeto que implementaIPrincipal
.No hay otro tipo de usuario que ASP.NET use en
User
este momento (pero eso no quiere decir que otra cosa no pueda implementarIPrincipal
).Entonces, si tiene algo que depende del 'nombre de usuario actual' que desea inyectar, debería inyectar
IPrincipal
y definitivamente noIHttpContextAccessor
.Importante: No pierda el tiempo inyectando
IPrincipal
directamente en su controlador o método de acción, no tiene sentido yaUser
que ya está disponible para usted.En
startup.cs
:Luego, en su objeto DI que necesita el usuario que acaba de inyectar
IPrincipal
para obtener el usuario actual.Lo más importante aquí es que si está haciendo pruebas unitarias, no necesita enviar una
HttpContext
, pero solo necesita burlarse de algo que representa loIPrincipal
que puede serClaimsPrincipal
.Una cosa extra importante de la que no estoy 100% seguro. Si necesita acceder a los reclamos reales
ClaimsPrincipal
, debe enviarlosIPrincipal
aClaimsPrincipal
. Esto está bien ya que sabemos al 100% que en tiempo de ejecución es de ese tipo (ya que esoHttpContext.User
es lo que es). De hecho, me gusta hacer esto en el constructor, ya que sé con certeza que cualquieraIPrincipal
será aClaimsPrincipal
.Si te estás burlando, solo crea uno
ClaimsPrincipal
directamente y pásalo a lo que sea necesarioIPrincipal
.Exactamente por qué no hay interfaz porque
IClaimsPrincipal
no estoy seguro. Supongo que MS decidió queClaimsPrincipal
era solo una 'colección' especializada que no garantizaba una interfaz.fuente
null
para el inyectadoIPrincipal
. También necesitaba agregar el servicio transitorio como…GetService<IHttpContextAccessor>()?.HttpContext.User…
(con el?
) porque de lo contrario se bloquearía (GetService devuelve nulo).services.AddTransient(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
como HttpContext.User es un ClaimsPrincipal.Parece que a partir de ahora (abril de 2017) funciona lo siguiente:
Al menos dentro de un
Controller
fuente
=>
operador utilizado así antes, se llama "Definición del cuerpo de expresión" y se describe en esta documentación . Por si acaso la gente como yo se preguntaba.IIdentity
astring
, como también se indica en el comentario superior. La edición simplemente solucionó eso. Tampoco estoy seguro de cómo llegó a su conclusión (en particular, ya que los puntos de "editor" se otorgan solo a usuarios con una reputación inferior a 2k).Quizás no vi la respuesta, pero así es como lo hago.
Necesita cambiar estos valores
Startup.cs -> ConfigureServices (...)
MVC o controlador de API web
Método del controlador:
El resultado es userName, por ejemplo, = dominio \ nombre de usuario
fuente
Mi problema era acceder al Usuario conectado como un objeto en el archivo cshtml. Teniendo en cuenta que deseaba el usuario en ViewData, este enfoque podría ser útil:
En el archivo cshtml
fuente
Además de las respuestas existentes, me gustaría agregar que también puede tener una instancia de clase disponible en toda la aplicación que contiene datos relacionados con el usuario como
UserID
etc.Puede ser útil para refactorizar, p. no desea buscar
UserID
en cada acción del controlador y declarar unUserID
parámetro adicional en cada método relacionado con la capa de servicio.He hecho una investigación y aquí está mi publicación .
Simplemente extienda su clase de la que deriva
DbContext
agregandoUserId
propiedad (o implemente unaSession
clase personalizada que tenga esta propiedad).A nivel de filtro, puede buscar su instancia de clase y establecer el
UserId
valor.Después de eso, donde sea que inyecte su instancia, tendrá los datos necesarios (la vida útil debe ser por solicitud , por lo que debe registrarla utilizando el
AddScoped
método).Ejemplo de trabajo:
Para más información mira mi respuesta .
fuente
Tomar
IdentityUser
también funcionaría. Este es un objeto de usuario actual y se pueden recuperar todos los valores de usuario.fuente
Si está utilizando la identidad escaneada y está utilizando Asp.net Core 2.2+, puede acceder al usuario actual desde una vista como esta:
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-2.2&tabs=visual-studio
fuente
Esta es una pregunta antigua, pero mi caso muestra que mi caso no se discutió aquí.
Me gusta más la respuesta de Simon_Weaver ( https://stackoverflow.com/a/54411397/2903893 ). Explica en detalle cómo obtener el nombre de usuario utilizando IPrincipal e IIdentity. Esta respuesta es absolutamente correcta y recomiendo usar este enfoque. Sin embargo, durante la depuración me encontré con el problema cuando ASP.NET NO puede completar correctamente el principio de servicio . (o en otras palabras, IPrincipal.Identity.Name es nulo)
Es obvio que para obtener el nombre de usuario MVC Framework debería tomarlo de alguna parte. En el mundo .NET, ASP.NET o ASP.NET Core está utilizando el middleware Open ID Connect. En el escenario simple, las aplicaciones web autentican a un usuario en un navegador web. En este escenario, la aplicación web dirige al navegador del usuario para que inicie sesión en Azure AD. Azure AD devuelve una respuesta de inicio de sesión a través del navegador del usuario, que contiene notificaciones sobre el usuario en un token de seguridad. Para que funcione en el código de su aplicación, deberá proporcionar la autoridad a la que sus aplicaciones web delegan el inicio de sesión. Cuando implementa su aplicación web en Azure Service, el escenario común para cumplir con estos requisitos es configurar la aplicación web: "App Services" -> YourApp -> "Authentication / Authorization" blade -> "App Service Authenticatio" = "On"https://github.com/Huachao/azure-content/blob/master/articles/app-service-api/app-service-api-authentication.md ). Creo (esta es mi suposición educada) que, bajo el capó de este proceso, el asistente ajusta la configuración web "principal" de esta aplicación web al agregar la misma configuración que muestro en los siguientes párrafos. Básicamente, el problema por el cual este enfoque NO funciona en ASP.NET Core es porque webconfig ignora la configuración de la máquina "principal". (Esto no es 100% seguro, solo doy la mejor explicación que tengo). Por lo tanto, para que funcione, debe configurarlo manualmente en su aplicación.
Aquí hay un artículo que explica cómo configurar tu aplicación de manera manual para usar Azure AD. https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/aspnetcore2-2
Paso 1: registre la muestra con su inquilino de Azure AD. (Es obvio, no quiero pasar mi tiempo de explicaciones).
Paso 2: en el archivo appsettings.json: reemplace el valor de ClientID con el ID de la aplicación que registró en el portal de registro de aplicaciones en el Paso 1. reemplace el valor de TenantId con common
Paso 3: abra el archivo Startup.cs y en el método ConfigureServices, después de la línea que contiene .AddAzureAD inserte el siguiente código, que permite que su aplicación inicie sesión en los usuarios con el punto final de Azure AD v2.0, que es tanto Work como School y Cuentas personales de Microsoft.
Resumen : He mostrado un posible problema más que podría dar lugar a un error que explica el iniciador del tema. La razón de este problema son las configuraciones faltantes para Azure AD (middleware de ID abierta). Para resolver este problema, propongo configurar manualmente "Autenticación / Autorización". Se agrega la breve descripción general de cómo configurar esto.
fuente
La mayoría de las respuestas muestran cómo manejar mejor
HttpContext
la documentación, que también es lo que utilicé.Quería mencionar que querrá verificar la configuración de su proyecto al depurar, el valor predeterminado es
Enable Anonymous Authentication = true
.fuente
Tengo mi solucion
fuente