ChatGPT解决这个技术问题 Extra ChatGPT

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

我之前使用 User.Identity.GetUserId() 使用 MVC5 完成了此操作,但这似乎在这里不起作用。 User.Identity 没有 GetUserId() 方法。

我正在使用 Microsoft.AspNet.Identity

试试这个System.Web.HttpContext.Current.User.Identity.Name
谢谢@PravinDeshmukh,但返回的是用户名而不是 id
它应该工作。请参阅 asp.net github.com/aspnet/Identity/blob/… 中的示例。只需确保用户已登录。@PravinDeshmukh,永远不要在 vnext 中使用 System.Web.HttpContext.Current :)
嗨@user960567,你能告诉我们为什么吗?
@PravinDeshmukh 因为它不能在 .NET 核心上运行,并且没有 System.Web 依赖项。

T
TanvirArjel

在 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
        
        // For ASP.NET Core <= 3.1
        ApplicationUser applicationUser = await _userManager.GetUserAsync(User);
        string userEmail = applicationUser?.Email; // will give the user's Email

       // For ASP.NET Core >= 5.0
       var userEmail =  User.FindFirstValue(ClaimTypes.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);
   }
}

然后您应该在 Startup 类中注册 IHttpContextAccessor,如下所示:

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

但在我的情况下,用户返回 null 吗?我在哪里做错了?
你确定你是用用户登录的吗?
我的场景就像我想要登录我的系统的用户的用户名。让它成为 Ubuntu 还是 Windows?当我在 Windows 中测试这个时,我以我的名字登录。但它正在返回 null
那得看你的代码了!可能是任何外部代理在这里发挥作用。
我发现如果您从 User.Identity.Name 得到空结果,可能是因为启用了匿名身份验证。通过展开 Properties > launchSettings.json 并将 anonymousAuthentication 设置为 false 并将 windowsAuthentication 设置为 true,我能够让 User.Identity.Name 返回我的域和用户名。
A
AmiNadimi

直到 ASP.NET Core 1.0 RC1:

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

从 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 这样的单行编写方法来做到这一点,但它不尊重单一职责原则。最好隔离获取用户的方式,因为如果有一天你决定改变你的用户管理系统,比如使用身份以外的其他解决方案,那将会很痛苦,因为你必须审查你的整个代码。


我有 System.Security.Claims 命名空间和 Microsoft.AspNet.Identity 程序集。
我认为这个答案比公认的答案更好,特别是因为 asp.net 核心正在促进依赖注入。
似乎是错误的方式,因为 userManager 将向数据库发出请求以检索有关用户的信息。在这种情况下 userId 已经在 HttpContext.User 中可用
@incognito 标识符只是一个示例,但您可以使用用户对象获取所需的所有信息
@Adrien,但问题是如何获取用户 ID。只是想说提供的方式不是最有效的。对于这种情况,我更喜欢 Soren 的回答或可以在评论中找到的较短版本。
H
Hamza Khanzada

你可以在你的控制器中得到它:

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

较短的版本:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
请注意,此扩展方法仅适用于控制器内部的用户,而不是视图组件,因为视图组件 User 属于 IPrincipal
@AK 您可以使用 Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier)) 获取整数 UserId
@HamzaKhanzada 是的,它有效,但看起来又长又丑。
此代码返回 204,无内容。有什么帮助吗?
n
niico

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

注意:我已经使用了 Microsoft.AspNet.Identity 但无法获得扩展方法。所以我想它们都必须相互结合使用

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

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


这是秘诀,但对于任何在添加这些用法后看起来的人来说... var userId = User.GetUserId();
ClaimsPrincipal (Controller.User) 的 .GetUserId() 扩展已移至 => UserManager.GetUserId(User);
使用 System.Security.Claims; var userId = this.User.FindFirst(ClaimTypes.NameIdentifier);
为以前有效的答案竖起大拇指,并正确识别新的“正确”答案。
抱歉,新的正确答案是什么?编辑说这是过时的,其他 2 个答案过时了???
A
AmiNadimi

仅适用于 .NET Core 2.0 在 Controller 类中获取登录用户的用户 ID 需要以下内容:

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

或者

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

例如

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

M
Menno Guldemond

如本文某处所述,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 添加到您的服务中。否则应该已经是这种情况了。


M
Mansur Haider

你必须导入 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 及更高版本的任何人,这就是您的答案
在 .NET Core 3.1 的 Web API + JWT 设置中测试。我想要一个基本控制器中当前登录的用户,这效率不高,从数据库中查询每个请求的用户等。有没有办法在不查询数据库的情况下获取当前用户?
为什么我的 User.FindFirstValue(ClaimTypes.NameIdentifier); 会返回 "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
S
Sum None

在 .net core 3.1(和其他更新的版本)中,您可以使用:

private readonly UserManager<IdentityUser> _userManager;

public ExampleController(UserManager<IdentityUser> userManager)
{
    _userManager = userManager;
}

然后:

string userId = _userManager.GetUserId(User);

或异步:

var user = await _userManager.GetUserAsync(User);
var userId = user.Id;

在这一点上,我试图弄清楚为什么你会使用一个而不是另一个。我知道异步的一般好处,但看到这两个经常使用。如果有人知道,请发表一些评论。


它可以在哪里找到这些的官方文档?
@KrishnadasPC 好问题。我不确定。但是,我将它们从类似这里的地方拉出来:docs.microsoft.com/en-us/aspnet/core/security/authentication/…
j
jv_

对于 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,
        });
    }

回复:

https://i.stack.imgur.com/rnZ4y.png


根据我的测试,this.User.Identity.Name 往往是用户名。在我的测试中,用户名是电子邮件,是用户通过注册登录或从外部登录(例如,Facebook、Google)登录。以下代码返回 userId。我为我的身份用户表使用自动递增的主键,因此使用 int.Parse。 int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
FindByIdAsync 不起作用,因为您提供了用户名。当您将其替换为 FindByNameAsync 时,它会起作用。
D
David Liang

对于 ASP.NET 5.0,我有一个扩展方法如下:

using System;
using System.ComponentModel;
using System.Security.Claims;

namespace YOUR_PROJECT.Presentation.WebUI.Extensions
{
    public static class ClaimsPrincipalExtensions
    {
        public static TId GetId<TId>(this ClaimsPrincipal principal)
        {
            if (principal == null || principal.Identity == null || 
                !principal.Identity.IsAuthenticated)
            {
                throw new ArgumentNullException(nameof(principal));
            }

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

            if (typeof(TId) == typeof(string) || 
                typeof(TId) == typeof(int) || 
                typeof(TId) == typeof(long) || 
                typeof(TId) == typeof(Guid))
            {
                var converter = TypeDescriptor.GetConverter(typeof(TId));

                return (TId)converter.ConvertFromInvariantString(loggedInUserId);
            }

            throw new InvalidOperationException("The user id type is invalid.");
        }

        public static Guid GetId(this ClaimsPrincipal principal)
        {
            return principal.GetId<Guid>();
        }
    }
}

所以你可以像这样使用它:

using Microsoft.AspNetCore.Mvc;
using YOUR_PROJECT.Presentation.WebUI.Extensions;

namespace YOUR_PROJECT.Presentation.WebUI.Controllers
{
    public class YourController :Controller
    {
        public IActionResult YourMethod()
        {
            // If it's Guid
            var userId = User.GetId();

            // Or
            // var userId = User.GetId<int>();

            return View();
        }
    }
}

principal,缺少 FindFirstValue,如果您记下我们需要的额外包,那就太好了
是否缺少 Microsoft.AspNet.Identity?我很久以前做过这个项目,我不记得那是什么包,我现在也没有对这个项目的引用。因此,如果您发现它,请提出修改建议。
Microsoft.Extensions.Identity.Code,这就是包...而且我还有一个问题,即在我的服务中我引用了 System.Web.MVC 或类似的东西,所以我试图传递的用户是 IPrincipal 而不是 ClaimPrincipal (我正在从 .NET 4.7 迁移到 .net 核心,只是因为我无法在 Rider 中发布我的旧项目(非核心),而且我的 PC 没有更多空间供 VS 尝试)
似乎新项目(不确定.Net 5,肯定是 6,应该参考框架而不是查找每个参考)这可以作为示例项目完成,通过添加... <PropertyGroup><TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> found sample,似乎是比 .net 5 早得多
P
Peter Kühne

APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

这样的事情你会得到索赔


A
Ahmad

尽管 Adrien 的答案是正确的,但您可以在一行中完成所有操作。不需要额外的功能或混乱。

它工作我在 ASP.NET Core 1.0 中检查过

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

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


我使用方法的原因是为了尊重单一责任原则。如果您不隔离获取用户的方式,那么如果有一天您决定修改用户管理系统,例如使用身份以外的其他解决方案,那将是痛苦的。
H
HO3EiN

为了在 razor 视图中获取当前用户 ID,我们可以像这样在视图中注入 UserManager:

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

希望对你有帮助。


M
Maksud

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



    }
}

在插入操作中获取用户 ID 和名称

_iPCommon.GetUserId();

谢谢,马克苏德


必须在 Startup.cs 中注册 IHttpContextAccessor 吗?
没有 REMESQ ,我没有将它注入到启动中,而是在我的应用程序中工作
O
Ogglas

如果您使用的是 JWT 令牌,则此代码有效:

User.FindFirstValue("sub");

M
Mosta

使用可以使用

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

由于某种原因,NameIdentifier 现在检索用户名(.net core 2.2)


j
jelde015

确保您已启用 Windows 身份验证。如果您启用了匿名身份验证,您可能会得到一个空字符串。

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio


Z
Zeeshan Safdar

我知道已经发布了很多答案,但也许它会像对我一样帮助某人。

我将两种解决方案合二为一,我能够获取登录用户及其数据。我使用的是 DotNet 5。按照代码,帮助获取登录用户。

var user = await _userManager.FindByNameAsync(HttpContext.User.Identity.Name);

我为 _userManager 使用了以下包

using Microsoft.AspNetCore.Identity;

对于 HttpContext,我从 ControllerBase 继承了我的控制器,对于 ControllerBase 类,我使用了以下包

using Microsoft.AspNetCore.Mvc;

D
DavidLyonsGarcia

TLDR:

在控制器中添加:

using System.Security.Claims; 

然后你可以使用:

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

TLDR 结束;

只是在 dot net 6 中测试如何获取用户 ID 并在默认的 Blazor WebAssembly Core Hosted 中测试它的简单方法:

我在名为 userId 的 WeatherForecast 类中添加了一个字符串 public class WeatherForecast { public DateTime Date { get;放; } 公共 int 温度 C { 获取;放; } 公共字符串?摘要{得到;放; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);公共字符串用户 ID { 获取;放; } = "不";然后在 WeatherForecastController

我使用 System.Security.Claims 添加;

在 GET 方法中,我将 WeatherForecast.userId 设置为 User.FindFirstValue(ClaimTypes.NameIdentifier): public IEnumerable Get() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime. Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)], userId = User.FindFirstValue(ClaimTypes.NameIdentifier) }) 。 ToArray(); }

最后在 FetchData.razor 中,我将表格修改为:

    <table class="table">
    <thead>
        <tr>
            <th>Date</th>
            <th>Temp. (C)</th>
            <th>Temp. (F)</th>
            <th>Summary</th>
            <th>User Id</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var forecast in forecasts)
        {
            <tr>
                <td>@forecast.Date.ToShortDateString()</td>
                <td>@forecast.TemperatureC</td>
                <td>@forecast.TemperatureF</td>
                <td>@forecast.Summary</td>
                <td>@forecast.userId</td>
            </tr>
        }
    </tbody>
</table>

https://i.stack.imgur.com/Fg9c7.png

我希望它有所帮助,因为在 net core 6 中有时很难找到答案


D
Diego Venâncio

作为处理其他人配置文件的管理员并且您需要获取您正在处理的配置文件的 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);
    }

E
Elan Hasson

如果您想在 ASP.NET MVC 控制器中使用它,请使用

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

您需要添加 using 语句,因为没有它就没有 GetUserId()


是的,我在问题中包括了“使用 Microsoft.AspNet.Identity”。我想出了如何解决它,虽然我在帖子上的回答
FWIW 它是(现在)User.GetUserId() 而不是 User.Identity.GetUserId()
问题是关于 asp.net CORE,它具有命名空间 Microsoft.AspNetCore.Identity;而不是 Microsoft.AspNet.Identity;并且使用该新命名空间没有 GetUserId() 扩展方法。这个答案是错误的!