Як отримати поточний авторизований ідентифікатор користувача в ASP.NET Core


179

Я робив це раніше з використанням MVC5, User.Identity.GetUserId()але це, здається, не працює тут. У методу User.Identityне єGetUserId()

я використовую Microsoft.AspNet.Identity


2
спробувати це System.Web.HttpContext.Current.User.Identity.Name?
Правін Дешмух

Дякую @PravinDeshmukh, але це повертає ім’я користувача, а не ідентифікатор
MRainzo

1
Це має працювати. Дивіться зразки в asp.net github.com/aspnet/Identity/blob/… . Просто переконайтесь, що користувач увійшов у систему. @PravinDeshmukh, ніколи не використовуйте System.Web.HttpContext.Current in 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;
     }
}

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.Claimspace namespace.

Оскільки 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, це стане болісним, оскільки вам доведеться переглянути весь код.


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
Hamza

1
@HamzaKhanzada Так, це працює, але виглядає так довго і потворно.
АК

39

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

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

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

EDIT : Ця відповідь застаріла. Подивіться на відповідь Сорена або Адрієна щодо датованого способу досягнення цього в CORE 1.0


17
Це був секретний соус, але для тих, хто захоче, після того, як ви додасте ці вживання, це ... var userId = User.GetUserId();
Самурай Кен

4
розширення .GetUserId () з ClaimsPrincipal (Controller.User) переміщено до => UserManager.GetUserId (Користувач);
Сорен

1
використання System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
Переключитись

3
Великі пальці вказують на попередньо дійсну відповідь і правильно визначають нову "правильну" відповідь.
pimbrouwers

26

Тільки для .NET Core 2.0 Щоб отримати UserID зареєстрованого користувача в 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. Конграц!
Просто ярмарок

це воно. Хтось із .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);?
puerile

5

Хоча відповідь Адрієна правильна, ви можете зробити це все в один рядок. Не потрібно додаткової функції чи безладу.

Він працює, я перевірив його в ASP.NET Core 1.0

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

тоді ви можете отримати інші властивості змінної на кшталт user.Email. Я сподіваюся, що це комусь допоможе.


3
Причиною, чому я використовую метод, є дотримання принципу єдиної відповідальності. Якщо ви не виділите спосіб отримання користувача, це буде болісно, ​​якщо коли-небудь ви вирішите змінити систему управління користувачами, наприклад, використовуйте інше рішення, ніж Identity.
AdrienTorris

5

Для ASP.NET Core 2.0, Entity Framework Core 2.0, AspNetCore.Identity 2.0 api ( 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,
        });
    }

Відповідь:

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


На основі мого тесту, this.User.Identity.Nameяк правило, це ім'я користувача. На моєму тесті, ім’я користувача - це електронна адреса, будь-яка реєстрація користувача з реєстрації або вхід із зовнішнього входу (наприклад, Facebook, Google). Наступний код повертає userId. Я використовую автоматично збільшений первинний ключ для таблиці моєї ідентичності користувача, отже, 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));
        }



    }
}

отримати userId та ім’я у дії вставки

_iPCommon.GetUserId();

Спасибі, Максуде


1
Вам потрібно зареєструвати IHttpContextAccessor в Startup.cs?
REMESQ

1
Ні REMESQ, я не вводив це в запуск, але працюючи в моїй програмі
Максуд

1

Щоб отримати поточний ідентифікатор користувача у видах бритви, ми можемо вставити UserManager у подання таким чином:

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

Сподіваюсь, вам це стане в нагоді.


0

використання може використовувати

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

чомусь NameIdentifier тепер отримає ім’я користувача (.net core 2.2)


0

Оскільки адміністратор, який працює над профілем інших людей, і вам потрібно отримати ідентифікатор профілю, над яким ви працюєте, ви можете використовувати ViewBag для захоплення ідентифікатора, наприклад ViewBag.UserId = userId; while 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
Питання було і є abou asp.net CORE, який має простір імен Microsoft.AspNetCore.Identity; і НЕ Microsoft.AspNet.Identity; І за допомогою цього нового простору імен НЕ існує метод розширення GetUserId (). ЦЕ ВІДПОВІДЬ НЕПРАВНИЙ!
Паскаль

4
Просто на ВСІХ КАПСАХ І дізнайтеся про те, як бути приємним на SO. stackoverflow.blog/2018/04/26 / ...
smoore4
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.