Para obtener el usuario actualmente conectado en MVC5, todo lo que teníamos que hacer era:
using Microsoft.AspNet.Identity;
[Authorize]
public IHttpActionResult DoSomething() {
string currentUserId = User.Identity.GetUserId();
}
Ahora, con ASP.NET Core pensé que esto debería funcionar, pero arroja un error.
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);
}
¿Algunas ideas?
EDITAR: La respuesta de Gerardo está bien encaminada, pero para obtener la "Id" real del usuario, esto parece funcionar:
ClaimsPrincipal currentUser = this.User;
var currentUserID = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
.GetUserAsync()
es más lento porque va al DB.Respuestas:
Suponiendo que su código está dentro de un controlador MVC:
public class MyController : Microsoft.AspNetCore.Mvc.Controller
De la
Controller
clase base, puede obtener elIClaimsPrincipal
de laUser
propiedadSystem.Security.Claims.ClaimsPrincipal currentUser = this.User;
Puede verificar las reclamaciones directamente (sin un viaje de ida y vuelta a la base de datos):
bool IsAdmin = currentUser.IsInRole("Admin"); var id = _userManager.GetUserId(User); // Get user id:
Se pueden obtener otros campos de la entidad Usuario de la base de datos:
Obtenga el administrador de usuarios usando la inyección de dependencia
private UserManager<ApplicationUser> _userManager; //class constructor public MyController(UserManager<ApplicationUser> userManager) { _userManager = userManager; }
Y úsalo:
var user = await _userManager.GetUserAsync(User); var email = user.Email;
fuente
IHttpContextAccessor
con Inyección de dependencia y luego obtenerla delUser
contexto http. Sólo tiene que añadir este parámetro al constructor de clase de servicio:IHttpContextAccessor contextAccessor
. Mantenga el descriptor de acceso en un campo_contextAccessor
y luego en los métodos de servicio para obtenerlo_contextAccessor.HttpContext.User
.Si está utilizando Bearing Token Auth, los ejemplos anteriores no devuelven un usuario de la aplicación.
En su lugar, use esto:
ClaimsPrincipal currentUser = this.User; var currentUserName = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value; ApplicationUser user = await _userManager.FindByNameAsync(currentUserName);
Esto funciona en apsnetcore 2.0. No lo he probado en versiones anteriores.
fuente
Para el contexto, creé un proyecto usando la plantilla de aplicación web ASP.NET Core 2. Luego, seleccione la Aplicación web (MVC), luego presione el botón Cambiar autenticación y seleccione Cuentas de usuario individuales.
Hay mucha infraestructura construida para usted a partir de esta plantilla. Busque
ManageController
en la carpeta Controladores.Este
ManageController
constructor de clase requiere que se complete esta variable UserManager:private readonly UserManager<ApplicationUser> _userManager;
Luego, eche un vistazo al método [HttpPost] Index de esta clase. Obtienen el usuario actual de esta manera:
var user = await _userManager.GetUserAsync(User);
Como nota adicional, aquí es donde desea actualizar los campos personalizados del perfil de usuario que ha agregado a la tabla AspNetUsers. Agregue los campos a la vista, luego envíe esos valores al IndexViewModel que luego se envía a este método de publicación. Agregué este código después de la lógica predeterminada para configurar la dirección de correo electrónico y el número de teléfono:
fuente
En .NET Core 2.0, el usuario ya existe como parte del controlador heredado subyacente. Simplemente use el Usuario como lo haría normalmente o pase a cualquier código de repositorio.
[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" }); } }
De aquí es de donde lo hereda
#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; }
fuente
Solo si alguien está interesado, esto funcionó para mí. Tengo una identidad personalizada que usa int para una clave principal, así que anulé el método GetUserAsync
Anular GetUserAsync
public override Task<User> GetUserAsync(ClaimsPrincipal principal) { var userId = GetUserId(principal); return FindByNameAsync(userId); }
Obtener usuario de identidad
var user = await _userManager.GetUserAsync(User);
Si está utilizando una clave principal de Guid normal, no es necesario que anule GetUserAsync. Todo esto asumiendo que su token está configurado correctamente.
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; }
fuente
private readonly UserManager<AppUser> _userManager; public AccountsController(UserManager<AppUser> userManager) { _userManager = userManager; } [Authorize(Policy = "ApiUser")] [HttpGet("api/accounts/GetProfile", Name = "GetProfile")] public async Task<IActionResult> GetProfile() { var userId = ((ClaimsIdentity)User.Identity).FindFirst("Id").Value; var user = await _userManager.FindByIdAsync(userId); ProfileUpdateModel model = new ProfileUpdateModel(); model.Email = user.Email; model.FirstName = user.FirstName; model.LastName = user.LastName; model.PhoneNumber = user.PhoneNumber; return new OkObjectResult(model); }
fuente
He puesto algo como esto en mi clase Controller y funcionó:
IdentityUser user = await userManager.FindByNameAsync(HttpContext.User.Identity.Name);
donde userManager es una instancia de la clase Microsoft.AspNetCore.Identity.UserManager (con toda la configuración extraña que la acompaña).
fuente