ASP.NET Core Identity - получить текущий пользователь

26

Чтобы получить зарегистрированного пользователя в MVC5, нам нужно было только:

using Microsoft.AspNet.Identity;
[Authorize]
public IHttpActionResult DoSomething() {
    string currentUserId = User.Identity.GetUserId();
}

Теперь, с ASP.NET Core, я думал, что это должно работать, но оно вызывает ошибку.

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

Любые идеи?

РЕДАКТИРОВАТЬ: Ответ Джерардо находится на пути, но для получения фактического «ИД» пользователя это работает:

ClaimsPrincipal currentUser = this.User;
var currentUserID = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
    
задан jbraun 03.08.2016 в 20:57
источник
  • Каков ваш вопрос? –  Gerardo Grignoli 04.08.2016 в 01:27
  • Вам нужен только идентификатор? Я отредактировал свой ответ, чтобы добавить, как его получить, используя более fancy _userManager.GetUserId (User) –  Gerardo Grignoli 04.08.2016 в 01:44
  • Да, в первую очередь мне нужен идентификатор из таблицы AspNetUsers или из сеанса. currentUser.FindFirst (ClaimTypes.NameIdentifier) ​​.Value дает идентификатор с использованием претензий. Он также работает с UserManager! Спасибо, Херардо! Является ли один из способов более эффективным, чем другой? –  jbraun 05.08.2016 в 00:02
  • UserManager внутренне выполняет .FindFirst (ClaimTypes.NameIdentifier). Так что это то же самое по производительности. Я предпочитаю инкапсуляцию usermanager для удобства чтения. С другой стороны .GetUserAsync () работает медленнее, потому что он переходит к БД. –  Gerardo Grignoli 05.08.2016 в 00:07
  • Я полностью согласен с Херардо. Спасибо ! –  jbraun 05.08.2016 в 03:40

4 ответа

49

Предполагая, что ваш код находится внутри контроллера MVC:

public class MyController : Microsoft.AspNetCore.Mvc.Controller

В базовом классе Controller вы можете получить IClaimsPrincipal из свойства User

System.Security.Claims.ClaimsPrincipal currentUser = this.User;

Вы можете проверить претензии напрямую (без обратной поездки в базу данных):

bool IsAdmin = currentUser.IsInRole("Admin");
var id = _userManager.GetUserId(User); // Get user id:

Другие поля могут быть получены из пользовательского объекта базы данных:

  1. Получить менеджеру пользователя, используя инъекцию зависимостей

    private UserManager<ApplicationUser> _userManager;
    
    //class constructor
    public MyController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }
    
  2. И используйте его:

    var user = await _userManager.GetUserAsync(User);
    var email = user.Email;
    
ответ дан Gerardo Grignoli 03.08.2016 в 21:11
источник
  • И если я в классе службы, а не в контроллере, где у меня нет пользовательского свойства? Как получить объект AppUser-объекта аутентифицированного пользователя? –  Kirsten 10.08.2016 в 23:56
  • @ Kirsten Вы можете получить IHttpContextAccessor с Injection Dependency Injection, а затем получить User из контекста http. Просто добавьте этот параметр в конструктор класса службы: IHttpContextAccessor contextAccessor. Храните аксессуар в поле _contextAccessor, а затем в методах службы его получите из _contextAccessor.HttpContext.User. –  Gerardo Grignoli 11.08.2016 в 17:36
  • @ Kirsten Но это делает ваш сервис с помощью ASP.NET Core, что делает его непригодным для использования в других сценариях. Это может быть приемлемо для вас или нет. Я также рассмотрю возможность передачи точно того, что вы хотите для службы при вызове метода. –  Gerardo Grignoli 11.08.2016 в 17:39
  • Вы подтолкнули меня правильно: я создал IUserService с GetUser и IsAuthenticated. В моем основном приложении ASP.NET у меня есть реализация userService, которая использует IHttpContextAccessor и UserManager <ApplicationUser>. Таким образом, моя служба UserService связана с ASP.NET Core, другими моими услугами нет. –  Kirsten 11.08.2016 в 18:06
  • Нет, они не ходят в базу данных. Проверяя источник, они не используют UserStore. github.com/dotnet/corefx/blob/master/src/System.Security.Claims/... github.com/aspnet/Identity/blob/... –  Gerardo Grignoli 11.05.2017 в 23:59
Показать остальные комментарии
3

В .NET Core 2.0 пользователь уже существует как часть базового унаследованного контроллера. Просто используйте пользователя, как обычно, или передайте любой код репозитория.

[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"
        });
    }
}

Здесь он наследует его от

#region Assembly Microsoft.AspNetCore.Mvc.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// C:\Users\BhailDa\.nuget\packages\microsoft.aspnetcore.mvc.core.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; }
    
ответ дан Bhail 24.11.2017 в 16:03
источник
2

Если вы используете Bearen Token Auth, приведенные выше примеры не возвращают пользователя приложения.

Вместо этого используйте это:

ClaimsPrincipal currentUser = this.User;
var currentUserName = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
ApplicationUser user = await _userManager.FindByNameAsync(currentUserName);

Это работает в apsnetcore 2.0. Не пытались в более ранних версиях.

    
ответ дан Greg0 02.02.2018 в 21:53
источник
  • работает для .net core 1.1 –  rock_walker 02.04.2018 в 21:19
0

В контексте я создал проект с использованием шаблона веб-приложения ASP.NET Core 2. Затем выберите веб-приложение (MVC), затем нажмите кнопку «Изменить аутентификацию» и выберите «Индивидуальные учетные записи пользователя».

Существует много инфраструктуры, созданной для вас из этого шаблона. Найдите ManageController в папке Controllers.

Этот конструктор класса ManageController требует, чтобы переменная UserManager заполнялась:

private readonly UserManager<ApplicationUser> _userManager;

Затем взгляните на метод индекса [HttpPost] в этом классе. Они получают текущего пользователя таким образом:

var user = await _userManager.GetUserAsync(User);

В качестве бонусного примечания, здесь вы хотите обновить любые настраиваемые поля в профиле пользователя, который вы добавили в таблицу AspNetUsers. Добавьте поля в представление, затем отправьте эти значения в IndexViewModel, который затем передается этому методу Post. Я добавил этот код после логики по умолчанию, чтобы установить адрес электронной почты и номер телефона:

user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Address1 = model.Address1;
user.Address2 = model.Address2;
user.City = model.City;
user.State = model.State;
user.Zip = model.Zip;
user.Company = model.Company;
user.Country = model.Country;
user.SetDisplayName();
user.SetProfileID();

_dbContext.Attach(user).State = EntityState.Modified;
_dbContext.SaveChanges();
    
ответ дан Joel Palmer 11.05.2018 в 22:15
источник