如何在ASP.NET Core中获取当前登录的用户ID


179

我之前使用MVC5做到了这一点,User.Identity.GetUserId()但是在这里似乎不起作用。本User.Identity可是没有的GetUserId()方法

我在用 Microsoft.AspNet.Identity


2
试试这个System.Web.HttpContext.Current.User.Identity.Name
Pravin Deshmukh 2015年

谢谢@PravinDeshmukh,但是它返回用户名而不是id
MRainzo 2015年

1
它应该工作。请参阅asp.netgithub.com/aspnet/Identity/blob/…中的示例。只要确保用户已登录即可。@PravinDeshmukh,切勿在vnext中使用System.Web.HttpContext.Current :)
user960567 2015年

1
嗨@ user960567,您能告诉我们为什么吗?
Pravin Deshmukh 2015年

@PravinDeshmukh,因为它在.NET核心上不起作用,并且没有System.Web依赖项。
user960567

Answers:


147

在ASP.NET Core版本> = 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);
   }
}

然后,您应该按照以下步骤IHttpContextAccessorStartup课程中注册:

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
但是在我的情况下,User返回的是null吗?我在哪里做错了?
Sruthi Varghese

您确定您已使用用户登录吗?
TanvirArjel

我的情况就像我要用户的用户名登录我的系统。设为Ubuntu还是Windows?当我在Windows中进行测试时,我以我的名字登录。但是它正在返回null
Sruthi Varghese

然后必须查看您的代码!可能是任何外部代理在这里起作用。
TanvirArjel

2
我发现,如果您从中得到的结果为空User.Identity.Name,则可能是因为启用了匿名身份验证。我能够获得User.Identity.Name通过扩大回到我的域名和用户名Properties > launchSettings.json,并设置anonymousAuthenticationfalse,并windowsAuthenticationtrue
安德鲁·格雷

109

直到ASP.NET Core 1.0 RC1为止:

System.Security.Claims命名空间中的User.GetUserId()。

由于ASP.NET 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将向数据库发出请求以检索有关用户的信息。在这种情况下,userId在HttpContext.User中已经可用
隐身

@incognito标识符只是一个示例,但您可以通过用户对象获取所需的所有信息
AdrienTorris

2
@Adrien,但问题是如何获取用户ID。只是想说提供的方法不是最有效的。对于这种情况,我希望索伦(Soren)回答或更短的版本(可以在评论中找到)。
隐身

90

您可以在控制器中获取它:

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
请注意,此扩展方法仅适用于控制器内部的User,不适用于视图组件,因为视图组件User是IPrincipal
adam3039 '17

@AK可以Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))用来获取整数UserId
Hamza Khanzada

1
@HamzaKhanzada是的,它可以工作,但是看起来又长又丑。
AK

39

我包括使用System.Security.Claims,并且可以访问GetUserId()扩展方法

注意:我已经使用过Microsoft.AspNet.Identity,但是无法获取扩展方法。因此,我认为它们必须相互结合使用

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

编辑:这个答案现在已经过时了。查看Soren或Adrien的答案以了解在CORE 1.0中实现此目标的过时方法


17
这是秘密的调味料,但是对于任何添加了这些用途的人来说,它都是...var userId = User.GetUserId();

4
ClaimsPrincipal(Controller.User)的.GetUserId()扩展名已移至=> UserManager.GetUserId(User);
索伦

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

如果您启动了一个空项目,则可能需要在Startup.cs中将UserManger添加到您的服务中。否则,情况应该已经如此。


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);
薄利多销

5

尽管Adrien的答案是正确的,但是您可以单行完成所有这些操作。无需额外的功能或混乱。

它在ASP.NET Core 1.0中检查过了

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

那么您可以获得变量的其他属性,例如user.Email。我希望这可以帮助别人。


2
我使用某种方法的原因是要尊重单一责任原则。如果您不孤立获取用户的方式,那么如果有朝一日您决定修改用户管理系统,例如使用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
Jasper

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
您是否必须在Startup.cs中注册IHttpContextAccessor?
REMESQ '18 -10-18

1
没有REMESQ,我没有将其注入启动程序,而是在我的应用程序中工作
Maksud

1

为了在剃刀视图中获得当前用户ID,我们可以在视图中注入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

作为管理其他人的个人资料的管理员,您需要获取正在使用的个人资料的ID,可以使用ViewBag捕获ID,例如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()扩展方法。这个答案是错误的!
Pascal

4
轻松实现全部大写。并了解如何对SO保持友好。 stackoverflow.blog/2018/04/26/...
smoore4
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.