Как получить текущий идентификатор пользователя вошедшего в систему в ASP.NET Core

179

Я делал это раньше с использованием MVC5, User.Identity.GetUserId()но здесь это не работает. User.IdentityОленья кожа имеет GetUserId()метод

Я использую Microsoft.AspNet.Identity

MRainzo
источник
2
попробовать это System.Web.HttpContext.Current.User.Identity.Name?
Правин Дешмукх
Спасибо @PravinDeshmukh, но это возвращает имя пользователя, а не идентификатор
MRainzo
1
Он должен работать. Смотрите примеры в asp.net github.com/aspnet/Identity/blob/… . Просто убедитесь, что пользователь вошел в систему. @PravinDeshmukh, никогда не используйте System.Web.HttpContext.Current в vnext :)
user960567
1
Привет @ user960567, расскажите, пожалуйста, почему?
Правин Дешмукх
@PravinDeshmukh, потому что он не будет работать на ядре .NET и нет зависимости System.Web.
user960567

Ответы:

148

Обновление в основной версии ASP.NET> = 2.0

В контроллере:

public class YourControllerNameController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;

    public YourControllerNameController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task<IActionResult> YourMethodName()
    {
        var userId =  User.FindFirstValue(ClaimTypes.NameIdentifier) // will give the user's userId
        var userName =  User.FindFirstValue(ClaimTypes.Name) // will give the user's userName

        ApplicationUser applicationUser = await _userManager.GetUserAsync(User);
        string userEmail = applicationUser?.Email; // will give the user's Email
    }
}

В каком-то другом классе:

public class OtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public OtherClass(IHttpContextAccessor httpContextAccessor)
    {
       _httpContextAccessor = httpContextAccessor;
    }

   public void YourMethodName()
   {
      var userId = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
   }
}

Тогда вы должны зарегистрироваться IHttpContextAccessorв Startupклассе следующим образом:

public void ConfigureServices(IServiceCollection services)
{
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

Для большей читабельности напишите методы расширения следующим образом:

public static class ClaimsPrincipalExtensions
{
    public static T GetLoggedInUserId<T>(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier);

        if (typeof(T) == typeof(string))
        {
            return (T)Convert.ChangeType(loggedInUserId, typeof(T));
        }
        else if (typeof(T) == typeof(int) || typeof(T) == typeof(long))
        {
            return loggedInUserId != null ? (T)Convert.ChangeType(loggedInUserId, typeof(T)) : (T)Convert.ChangeType(0, typeof(T));
        }
        else
        {
            throw new Exception("Invalid type provided");
        }
    }

    public static string GetLoggedInUserName(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        return principal.FindFirstValue(ClaimTypes.Name);
    }

    public static string GetLoggedInUserEmail(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        return principal.FindFirstValue(ClaimTypes.Email);
    }
}

Затем используйте следующее:

public class YourControllerNameController : Controller
{
    public IActionResult YourMethodName()
    {
        var userId = User.GetLoggedInUserId<string>(); // Specify the type of your UserId;
        var userName = User.GetLoggedInUserName();
        var userEmail = User.GetLoggedInUserEmail();
    }
}

public class OtherClass
{
     private readonly IHttpContextAccessor _httpContextAccessor;
     public OtherClass(IHttpContextAccessor httpContextAccessor)
     {
         _httpContextAccessor = httpContextAccessor;
     }

     public void YourMethodName()
     {
         var userId = _httpContextAccessor.HttpContext.User.GetLoggedInUserId<string>(); // Specify the type of your UserId;
     }
}
TanvirArjel
источник
1
Но пользователь возвращает ноль в моем случае? Где я делаю не так?
Срути Варгезе
Вы уверены, что вы вошли в систему с пользователем?
TanvirArjel
Мой сценарий похож на то, что я хочу, чтобы имя пользователя вошло в мою систему. Пусть это будет Ubuntu или Windows? И когда я тестирую это в Windows, я вошел под своим именем. Но это возвращается null.
Срути Варгезе
Тогда нужно увидеть ваш код! Может быть, любой внешний агент играет роль здесь.
TanvirArjel
2
Я обнаружил, что если вы получили нулевой результат User.Identity.Name, это может быть потому, что включена анонимная аутентификация. Я смог User.Identity.Nameвернуть свой домен и имя пользователя, расширив Properties > launchSettings.jsonи настроив anonymousAuthenticationдо falseи windowsAuthenticationдо true.
Эндрю Грей
109

До ASP.NET Core 1.0 RC1 :

Это User.GetUserId () из пространства имен System.Security.Claims .

Начиная с ASP.NET Core 1.0 RC2 :

Теперь вы должны использовать UserManager . Вы можете создать метод для получения текущего пользователя:

private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);

И получить информацию о пользователе с объектом:

var user = await GetCurrentUserAsync();

var userId = user?.Id;
string mail = user?.Email;

Примечание. Вы можете сделать это без использования метода, пишущего одинарными строками string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Email, но это не соответствует принципу единой ответственности. Лучше изолировать способ, которым вы получаете пользователя, потому что, если когда-нибудь вы решите изменить свою систему управления пользователями, например, использовать другое решение, чем Identity, это станет болезненным, поскольку вам придется просматривать весь код.

AdrienTorris
источник
1
У меня есть пространство имен System.Security.Claims и сборка Microsoft.AspNet.Identity.
scottheckel
2
Я думаю, что этот ответ лучше принятого, тем более что ядро ​​asp.net способствует внедрению зависимостей.
Филипп Дэвис,
2
Кажется неправильным, потому что userManager сделает запрос к базе данных, чтобы получить информацию о пользователе. И в этом случае идентификатор пользователя уже имеется в HttpContext.User
инкогнито
@incognito Идентификатор был просто примером, но вы можете получить всю необходимую информацию с помощью объекта пользователя
AdrienTorris,
2
@ Adrien, но вопрос был в том, как получить идентификатор пользователя. Просто хотел сказать, что предоставленный способ не самый эффективный. Для этого случая я бы предпочел ответить Сореном или более короткой версией, которую можно найти в комментариях.
инкогнито
91

вы можете получить его в своем контроллере:

using System.Security.Claims;
var userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

или напишите метод расширения, как раньше .Core v1.0

using System;
using System.Security.Claims;

namespace Shared.Web.MvcExtensions
{
    public static class ClaimsPrincipalExtensions
    {
        public static string GetUserId(this ClaimsPrincipal principal)
        {
            if (principal == null)
                throw new ArgumentNullException(nameof(principal));

            return principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        }
    }
}

и получить везде, где доступен пользователь ClaimsPrincipal :

using Microsoft.AspNetCore.Mvc;
using Shared.Web.MvcExtensions;

namespace Web.Site.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return Content(this.User.GetUserId());
        }
    }
}
Сорен
источник
16
Укороченная версия:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
CFreitas
1
Обратите внимание, что этот метод расширения работает только для пользователей внутри контроллеров, а не для компонентов просмотра, так как компонент представления имеет IPrincipal
adam3039,
@AK вы можете использовать, Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))чтобы получить целочисленный UserId
Хамза
1
@HamzaKhanzada Да, это работает, но выглядит так долго и безобразно.
АК
39

Я включил использование System.Security.Claims, и я мог получить доступ к методу расширения GetUserId ()

NB. Я уже использовал Microsoft.AspNet.Identity, но не смог получить метод расширения. Так что я думаю, что оба они должны использоваться в сочетании друг с другом

using Microsoft.AspNet.Identity;
using System.Security.Claims;

РЕДАКТИРОВАТЬ : Этот ответ сейчас устарел. Посмотрите на ответ Сорена или Адриена, чтобы узнать, как это сделать в CORE 1.0.

MRainzo
источник
17
Это был секретный соус, но для тех, кто смотрит после того, как вы добавите эти слова, это ... var userId = User.GetUserId();
Самурай Кен,
4
расширение .GetUserId () из ClaimsPrincipal (Controller.User) было перемещено в => UserManager.GetUserId (User);
Сорен
1
использование System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
Переключить
3
Недурно для ранее действительного ответа и правильного определения нового «правильного» ответа.
pimbrouwers
26

Только для .NET Core 2.0 Для получения идентификатора пользователя вошедшего в систему пользователя в Controllerклассе требуется следующее :

var userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

или

var userId = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);

например

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);
Оракул
источник
17

Как указано где-то в этом посте, метод GetUserId () был перемещен в UserManager.

private readonly UserManager<ApplicationUser> _userManager;

public YourController(UserManager<ApplicationUser> userManager)
{
    _userManager = userManager;
}

public IActionResult MyAction()
{
    var userId = _userManager.GetUserId(HttpContext.User);

    var model = GetSomeModelByUserId(userId);

    return View(model);
}

Если вы запустили пустой проект, вам может понадобиться добавить UserManger к вашим сервисам в startup.cs. В противном случае это уже должно быть.

Менно Гульдемон
источник
10

Вы должны импортировать Microsoft.AspNetCore.Identity & System.Security.Claims

// to get current user ID
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

// to get current user info
var user = await _userManager.FindByIdAsync(userId);
Мансур Хайдер
источник
из всех этих ответов только ваш работает с ASP.NET CORE v 2.0. Congratz!
Просто ярмарка
это оно. Кто-нибудь из .NET Core 2.0 и выше, это ваш ответ
alvinchesaro
1
Протестировано на .NET Core 3.1 в настройках Web API + JWT. Я хочу, чтобы текущий пользователь вошел в базовый контроллер, это неэффективно, он запрашивает пользователя из базы данных для каждого запроса и т. Д. Есть ли способ получить текущего пользователя, не запрашивая базу данных?
Nexus
почему мой вернуться "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"к User.FindFirstValue(ClaimTypes.NameIdentifier);?
ребяческий
5

Хотя ответ Адриен верен, вы можете сделать все это в одной строке. Нет необходимости в дополнительных функциях или беспорядке.

Это работает, я проверил это в ASP.NET Core 1.0

var user = await _userManager.GetUserAsync(HttpContext.User);

тогда вы можете получить другие свойства переменной, как user.Email. Я надеюсь, что это поможет кому-то.

Ahmad
источник
3
Причина, по которой я использую метод, заключается в уважении принципа единой ответственности. Если вы не изолируете способ, которым вы получаете пользователя, будет больно, если когда-нибудь вы решите изменить свою систему управления пользователями, например, использовать другое решение, чем Identity.
AdrienTorris
5

Для ASP.NET Core 2.0, Entity Framework Core 2.0, API-интерфейс AspNetCore.Identity 2.0 ( https://github.com/kkagill/ContosoUniversity-Backend ):

IdБыло измененоUser.Identity.Name

    [Authorize, HttpGet("Profile")]
    public async Task<IActionResult> GetProfile()
    {
        var user = await _userManager.FindByIdAsync(User.Identity.Name);

        return Json(new
        {
            IsAuthenticated = User.Identity.IsAuthenticated,
            Id = User.Identity.Name,
            Name = $"{user.FirstName} {user.LastName}",
            Type = User.Identity.AuthenticationType,
        });
    }

Отклик:

введите описание изображения здесь

jv_
источник
На основании моего теста, this.User.Identity.Nameкак правило, имя пользователя. В моем тесте имя пользователя - это электронное письмо, будь то пользователь, который вошел в систему после регистрации или вошел в систему с внешнего входа (например, Facebook, Google). Следующий код возвращает идентификатор пользователя. Я использую автоинкрементный первичный ключ для моей идентификационной пользовательской таблицы, следовательно, int.Parse. int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
Майкл Буэн
1
FindByIdAsyncне работает, поскольку вы предоставляете имя пользователя. Это работает, когда вы замените его FindByNameAsync.
Джаспер
4

в APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

Примерно так вы получите претензии

Усман
источник
1

User.Identity.GetUserId ();

не существует в ядре идентичности asp.net 2.0. В связи с этим мне удалось по-другому. я создал общий класс для использования всего приложения, потому что получаю информацию о пользователе.

создать общий класс PCommon и интерфейс IPCommon, добавив ссылкуusing System.Security.Claims

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Common.Web.Helper
{
    public class PCommon: IPCommon
    {
        private readonly IHttpContextAccessor _context;
        public PayraCommon(IHttpContextAccessor context)
        {
            _context = context;
        }
        public int GetUserId()
        {
            return Convert.ToInt16(_context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier));
        }
        public string GetUserName()
        {
            return _context.HttpContext.User.Identity.Name;
        }

    }
    public interface IPCommon
    {
        int GetUserId();
        string GetUserName();        
    }    
}

Здесь реализация общего класса

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Pay.DataManager.Concreate;
using Pay.DataManager.Helper;
using Pay.DataManager.Models;
using Pay.Web.Helper;
using Pay.Web.Models.GeneralViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Pay.Controllers
{

    [Authorize]
    public class BankController : Controller
    {

        private readonly IUnitOfWork _unitOfWork;
        private readonly ILogger _logger;
        private readonly IPCommon _iPCommon;


        public BankController(IUnitOfWork unitOfWork, IPCommon IPCommon, ILogger logger = null)
        {
            _unitOfWork = unitOfWork;
            _iPCommon = IPCommon;
            if (logger != null) { _logger = logger; }
        }


        public ActionResult Create()
        {
            BankViewModel _bank = new BankViewModel();
            CountryLoad(_bank);
            return View();
        }

        [HttpPost, ActionName("Create")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Insert(BankViewModel bankVM)
        {

            if (!ModelState.IsValid)
            {
                CountryLoad(bankVM);
                //TempData["show-message"] = Notification.Show(CommonMessage.RequiredFieldError("bank"), "Warning", type: ToastType.Warning);
                return View(bankVM);
            }


            try
            {
                bankVM.EntryBy = _iPCommon.GetUserId();
                var userName = _iPCommon.GetUserName()();
                //_unitOfWork.BankRepo.Add(ModelAdapter.ModelMap(new Bank(), bankVM));
                //_unitOfWork.Save();
               // TempData["show-message"] = Notification.Show(CommonMessage.SaveMessage(), "Success", type: ToastType.Success);
            }
            catch (Exception ex)
            {
               // TempData["show-message"] = Notification.Show(CommonMessage.SaveErrorMessage("bank"), "Error", type: ToastType.Error);
            }
            return RedirectToAction(nameof(Index));
        }



    }
}

получить идентификатор пользователя и имя в действии вставки

_iPCommon.GetUserId();

Спасибо Максуд

Максуд
источник
1
Нужно ли регистрировать IHttpContextAccessor в Startup.cs?
РЕМЕСК
1
Нет REMESQ, я не вводил это в автозагрузку, но работал в своем приложении
Максуд
1

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

@inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> _userManager
@{ string userId = _userManager.GetUserId(User); }

Я надеюсь, что вы найдете это полезным.

HO3EiN
источник
0

использовать можно использовать

string userid = User.FindFirst("id").Value;

по какой-то причине NameIdentifier теперь получает имя пользователя (.net core 2.2)

Моста
источник
0

Как администратор, работающий над профилем других людей, и вам необходимо получить идентификатор профиля, над которым вы работаете, вы можете использовать ViewBag для захвата идентификатора, например ViewBag.UserId = userId; userId - это строковый параметр метода, с которым вы работаете.

    [HttpGet]

    public async Task<IActionResult> ManageUserRoles(string userId)
    {

          ViewBag.UserId = userId;


        var user = await userManager.FindByIdAsync(userId);

        if (user == null)
        {
            ViewBag.ErrorMessage = $"User with Id = {userId} cannot be found";
            return View("NotFound");
        }

        var model = new List<UserRolesViewModel>();

        foreach (var role in roleManager.Roles)
        {
            var userRolesViewModel = new UserRolesViewModel
            {
                RoleId = role.Id,
                RoleName = role.Name
            };

            if (await userManager.IsInRoleAsync(user, role.Name))
            {
                userRolesViewModel.IsSelected = true;
            }
            else
            {
                userRolesViewModel.IsSelected = false;
            }

            model.Add(userRolesViewModel);
        }
        return View(model);
    }
Сэмми Акинсою
источник
-11

Если вы хотите это в ASP.NET MVC Controller, используйте

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

Вам нужно добавить usingзаявление, потому GetUserId()что без него не будет.

Правин Дешмукх
источник
2
Да, я включил в вопрос, что у меня есть «использование Microsoft.AspNet.Identity». Я выяснил, как решить эту проблему, хотя с моим ответом на пост
MRainzo
1
FWIW это (сейчас), User.GetUserId()а неUser.Identity.GetUserId()
lc.
18
Вопрос был и есть о asp.net CORE, который имеет пространство имен Microsoft.AspNetCore.Identity; а НЕ Microsoft.AspNet.Identity; И используя это новое пространство имен, НЕТ метода расширения GetUserId (). ЭТО ОТВЕТ НЕПРАВИЛЬНО!
Паскаль
4
Легко на все колпачки. И узнать о том, как хорошо на SO. stackoverflow.blog/2018/04/26/…
smoore4