ASP.NET Core身份-获取当前用户


81

要获得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);
}

有任何想法吗?

编辑: Gerardo的响应已步入正轨,但要获得用户的实际“ Id”,这似乎可行:

ClaimsPrincipal currentUser = this.User;
var currentUserID = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;

您到底要问什么?
Gerardo Grignoli,

您只需要ID?我编辑我的答案如何开始使用它更看中_userManager.GetUserId(用户)添加
赫拉尔Grignoli

是的,主要是我需要AspNetUsers表或会话中的ID。currentUser.FindFirst(ClaimTypes.NameIdentifier).Value使用Claims给出ID。它也可以与UserManager一起使用!谢谢杰拉多!一种方法比另一种更有效率吗?
jbraun '16

UserManager在内部执行.FindFirst(ClaimTypes.NameIdentifier)。因此,这是相同的性能。我更喜欢使用usermanager封装以便于阅读。另一方面.GetUserAsync(),由于它进入数据库,因此速度较慢。
Gerardo Grignoli

我完全同意Gerardo。谢谢 !
jbraun '16

Answers:


138

假设您的代码在MVC控制器中:

public class MyController : Microsoft.AspNetCore.Mvc.Controller

Controller基类中,您可以IClaimsPrincipalUser属性中获取

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

您可以直接检查声明(无需往返数据库):

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

可以从数据库的User实体中获取其他字段:

  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;
    

4
如果我在服务类中而不在控制器中,那么我没有用户属性?如何获取已认证用户的AppUser-Object?
Kirsten

13
@Kirsten您可以IHttpContextAccessor使用Dependency Injection接收,然后User从http上下文获取。只需将此参数添加到服务类构造函数:中即可 IHttpContextAccessor contextAccessor。将访问器放在字段上_contextAccessor,然后在服务方法上从获取它_contextAccessor.HttpContext.User
Gerardo Grignoli,

5
@Kirsten但是,这样做会使您的服务与ASP.NET Core耦合,从而使其无法在其他类型的方案中使用。这对于您来说是否可以接受。我还将考虑在方法调用中将所需的内容完全传递给服务。
Gerardo Grignoli,

2
您以正确的方式推动了我:我使用GetUser和IsAuthenticated构建了IUserService。在我的ASP.NET Core App中,我具有使用IHttpContextAccessor和UserManager <ApplicationUser>的实现userService。因此,我的userService已耦合到ASP.NET Core,而其他服务则没有。
Kirsten


31

如果您使用的是轴承令牌认证,则以上示例不会返回“应用程序用户”。

而是使用以下命令:

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

这适用于apsnetcore 2.0。尚未尝试在较早版本中使用。


我的令牌已通过验证,但未设置本金和声明。这是在dotnet core 2.1和2.2中发生的
-ps2goat

@ ps2goat,我将创建一个新问题来解决此问题,并包括创建令牌的代码。
格雷格·古姆

1
我想到了。我们没有默认方案,因为我们有5种不同的方案。我必须添加一个中间件来解码令牌,然后将声明分配给当前用户。我大概应该写一个问题并为其他人回答,因为我周围的情况很少。
ps2goat

1
ClaimTypes.Name获取我要查找的用户名而不是ID。ClaimTypes.NameIdentifier获取用户的ID。以防万一有人看到并想知道如何获取用户名。感谢您的回答,格雷格!
Matthew Zourelias

7

就上下文而言,我使用ASP.NET Core 2 Web应用程序模板创建了一个项目。然后,选择Web应用程序(MVC),然后单击“更改身份验证”按钮并选择“个人用户”帐户。

此模板为您构建了许多基础结构。找到ManageController在Controllers文件夹。

此类的ManageController构造函数需要填充以下UserManager变量:

private readonly UserManager<ApplicationUser> _userManager;

然后,查看此类中的[HttpPost] Index方法。他们以这种方式获取当前用户:

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

5

在.NET Core 2.0中,用户已经作为基础继承控制器的一部分存在。只需像平常一样使用User或传递到任何存储库代码即可。

[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\2.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; }

2

就算有人有兴趣,这对我也有帮助。我有一个使用int作为主键的自定义标识,因此我覆盖了GetUserAsync方法

覆盖GetUserAsync

public override Task<User> GetUserAsync(ClaimsPrincipal principal)
{
    var userId = GetUserId(principal);
    return FindByNameAsync(userId);
}

获取身份用户

var user = await _userManager.GetUserAsync(User);

如果您使用常规的Guid主键,则不需要覆盖GetUserAsync。所有这些都假设您的令牌已正确配置。

public async Task<string> GenerateTokenAsync(string email)
{
    var user = await _userManager.FindByEmailAsync(email);
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_tokenProviderOptions.SecretKey);

    var userRoles = await _userManager.GetRolesAsync(user);
    var roles = userRoles.Select(o => new Claim(ClaimTypes.Role, o));

    var claims = new[]
    {
        new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
        new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString(CultureInfo.CurrentCulture)),
        new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName),
        new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
        new Claim(JwtRegisteredClaimNames.Email, user.Email),
    }
    .Union(roles);

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(claims),
        Expires = DateTime.UtcNow.AddHours(_tokenProviderOptions.Expires),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);

    return Task.FromResult(new JwtSecurityTokenHandler().WriteToken(token)).Result;
}

1
private readonly UserManager<AppUser> _userManager;

 public AccountsController(UserManager<AppUser> userManager)
 {
            _userManager = userManager;
 }

[Authorize(Policy = "ApiUser")]
[HttpGet("api/accounts/GetProfile", Name = "GetProfile")]
public async Task<IActionResult> GetProfile()
{
   var userId = ((ClaimsIdentity)User.Identity).FindFirst("Id").Value;
   var user = await _userManager.FindByIdAsync(userId);

   ProfileUpdateModel model = new ProfileUpdateModel();
   model.Email = user.Email;
   model.FirstName = user.FirstName;
   model.LastName = user.LastName;
   model.PhoneNumber = user.PhoneNumber;

   return new OkObjectResult(model);
}

0

我在Controller类中放入了类似的内容,它的工作原理是:

IdentityUser user = await userManager.FindByNameAsync(HttpContext.User.Identity.Name);

其中,userManager是Microsoft.AspNetCore.Identity.UserManager类的实例(带有所有与此相关的怪异设置)。

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.