Aby uzyskać aktualnie zalogowanego użytkownika w MVC5, wszystko, co musieliśmy zrobić, to:
using Microsoft.AspNet.Identity;
[Authorize]
public IHttpActionResult DoSomething() {
string currentUserId = User.Identity.GetUserId();
}
Teraz myślę, że w przypadku ASP.NET Core to powinno działać, ale generuje błąd.
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);
}
Jakieś pomysły?
EDYCJA: odpowiedź Gerardo jest na dobrej drodze, ale aby uzyskać rzeczywisty „identyfikator” użytkownika, wydaje się, że działa:
ClaimsPrincipal currentUser = this.User;
var currentUserID = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
.GetUserAsync()
jest wolniejszy, ponieważ idzie do DB.Odpowiedzi:
Zakładając, że twój kod znajduje się wewnątrz kontrolera MVC:
public class MyController : Microsoft.AspNetCore.Mvc.Controller
Z
Controller
klasy bazowej można pobraćIClaimsPrincipal
zUser
właściwościSystem.Security.Claims.ClaimsPrincipal currentUser = this.User;
Możesz sprawdzić roszczenia bezpośrednio (bez podróży w obie strony do bazy danych):
bool IsAdmin = currentUser.IsInRole("Admin"); var id = _userManager.GetUserId(User); // Get user id:
Inne pola można pobrać z jednostki użytkownika bazy danych:
Pobierz menedżera użytkowników za pomocą iniekcji zależności
private UserManager<ApplicationUser> _userManager; //class constructor public MyController(UserManager<ApplicationUser> userManager) { _userManager = userManager; }
I użyj go:
var user = await _userManager.GetUserAsync(User); var email = user.Email;
źródło
IHttpContextAccessor
z Dependency Injection, a następnie pobraćUser
z kontekstu http. Wystarczy dodać ten param do konstruktora klasy usług:IHttpContextAccessor contextAccessor
. Zachowaj akcesor w polu,_contextAccessor
a następnie w metodach usługi pobierz go_contextAccessor.HttpContext.User
.Jeśli korzystasz z uwierzytelniania za pomocą tokenów łożysk, powyższe przykłady nie zwracają użytkownika aplikacji.
Zamiast tego użyj tego:
ClaimsPrincipal currentUser = this.User; var currentUserName = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value; ApplicationUser user = await _userManager.FindByNameAsync(currentUserName);
Działa to w apsnetcore 2.0. Nie próbowałem we wcześniejszych wersjach.
źródło
W kontekście utworzyłem projekt przy użyciu szablonu aplikacji sieci Web ASP.NET Core 2. Następnie wybierz aplikację internetową (MVC), a następnie naciśnij przycisk Zmień uwierzytelnianie i wybierz Indywidualne konta użytkowników.
Na podstawie tego szablonu zbudowano wiele infrastruktury. Znajdź
ManageController
w folderze Kontrolery.Ten
ManageController
konstruktor klasy wymaga wypełnienia tej zmiennej UserManager:private readonly UserManager<ApplicationUser> _userManager;
Następnie przyjrzyj się metodzie [HttpPost] Index w tej klasie. Bieżącego użytkownika uzyskują w ten sposób:
var user = await _userManager.GetUserAsync(User);
Jako dodatkowa uwaga, w tym miejscu chcesz zaktualizować dowolne pola niestandardowe do profilu użytkownika dodanego do tabeli AspNetUsers. Dodaj pola do widoku, a następnie prześlij te wartości do IndexViewModel, który jest następnie przesyłany do tej metody Post. Dodałem ten kod po domyślnej logice do ustawienia adresu e-mail i numeru telefonu:
źródło
W .NET Core 2.0 użytkownik już istnieje jako część podstawowego kontrolera dziedziczonego. Po prostu użyj użytkownika tak, jak zwykle lub przejdź do dowolnego kodu repozytorium.
[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" }); } }
Stąd go dziedziczy
#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; }
źródło
Jeśli ktoś jest zainteresowany, to zadziałało dla mnie. Mam niestandardową tożsamość, która używa int dla klucza podstawowego, więc zastąpiłem metodę GetUserAsync
Zastąp GetUserAsync
public override Task<User> GetUserAsync(ClaimsPrincipal principal) { var userId = GetUserId(principal); return FindByNameAsync(userId); }
Uzyskaj użytkownika tożsamości
var user = await _userManager.GetUserAsync(User);
Jeśli używasz zwykłego klucza podstawowego Guid, nie musisz zastępować GetUserAsync. Wszystko to przy założeniu, że token jest poprawnie skonfigurowany.
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; }
źródło
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); }
źródło
Umieściłem coś takiego w mojej klasie kontrolera i zadziałało:
IdentityUser user = await userManager.FindByNameAsync(HttpContext.User.Identity.Name);
gdzie userManager jest instancją klasy Microsoft.AspNetCore.Identity.UserManager (z całą dziwną konfiguracją, która się z tym wiąże).
źródło