Правильный способ получения текущего идентификатора пользователя в ядре Entity Framework

Существует множество разных ответов для разных RC-ов ASP.NET Core о том, как получить идентификатор текущего пользователя. Я хотел задать здесь определенный вопрос. Обратите внимание, что project.json теперь имеет "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0"

С RC1 вы можете сделать что-то вроде этого:

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

User.GetUserId();

Но с недавно выпущенной версией EF Core, Microsoft.AspNet.Identity не является правильной версией.

Были предложения использовать UserManager, который, похоже, очень просто, чтобы получить зарегистрированного пользователя:

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

var user = await GetCurrentUserAsync();
var userId = user?.Id;

Другим методом, который я нашел, был:

private readonly UserManager<ApplicationUser> _userManager;
_userManager.GetUserId(User)

Итак, с помощью RTM и Core EF Core 1 для .NET Framework 1 со следующими библиотеками в project.json, каков правильный способ получить идентификатор текущего пользователя в системе?

"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",

Ответ 1

Идентификатор ядра ASP.NET вводится через DI в startup.cs - как таковой вам просто нужно вводить UserManager через конструктор

UserManager<ApplicationUser> userManager

Затем вы можете использовать следующие методы

_userManager.GetUserId(User);

То, как он используется в примере веб-приложения при создании нового проекта ASP.NET Core 1 с индивидуальной учетной записью пользователя.

Ответ 2

Если вы получаете доступ к этому при работе с контроллером, то использование UserManager для получения идентификатора пользователя довольно неэффективно, поскольку вы делаете обратную поездку в базу данных. Если вы используете ClaimsIdentity, вы можете сделать что-то вроде этого, чтобы получить идентификатор пользователя:

var claimsIdentity = (ClaimsIdentity)this.User.Identity;
var claim = claimsIdentity.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
var userId = claim.Value;

Этот метод просто считывает идентификатор пользователя, который уже присутствует в файле cookie, который, в свою очередь, автоматически десериализуется и сохраняется в экземпляре ClaimsIdentity.

Я использую этот вспомогательный класс:

public static class UserHelpers
{
    public static string GetUserId(this IPrincipal principal)
    {
        var claimsIdentity = (ClaimsIdentity)principal.Identity;
        var claim = claimsIdentity.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
        return claim.Value;
    }
}

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

var userId = this.User.GetUserId();

Если по какой-либо причине требуемое требование отсутствует в сборке Claims, вы можете легко добавить его при создании пользователя ClaimsIdentity:

public class ApplicaionUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager)
    {
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        userIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, this.UserId));
        return userIdentity;
    }
}

Ответ 3

Ниже приведена более строгая версия других ответов.

var user = User.FindFirst(ClaimTypes.NameIdentifier).Value;

Чтобы объяснить немного дальше, я хотел использовать самую основную форму аутентификации без каких-либо таблиц в базе данных, поэтому я выбрал этот вариант - Использование аутентификации cookie без Идентификатора основного ядра ASP.NET из документации Core.

Чтобы получить эту работу, первым шагом является добавление сервисов в Startup.cs

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
        {
        options.LoginPath = new PathString("/Account/Login/");
        options.LogoutPath = new PathString("/Account/Logoff/");
        options.AccessDeniedPath = new PathString("/Account/AccessDenied/");
        options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
        });

services.ConfigureApplicationCookie(identityOptionsCookies =>
{
    // See https://andrewlock.net/automatically-validating-anti-forgery-tokens-in-asp-net-core-with-the-autovalidateantiforgerytokenattribute/
    identityOptionsCookies.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
});

Затем в AccountController в сообщении после ввода правильного идентификатора пользователя и пароля простейшая проверка подлинности на основе требований должна просто добавить идентификатор входа в качестве претензии, например.

var требует = новый список               {                   new Claim (ClaimTypes.NameIdentifier, loginViewModel.Guid, ClaimValueTypes.String, эмитент),               };

            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

            var principal = new ClaimsPrincipal(claimsIdentity);

            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal,
                new AuthenticationProperties
                {
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(_cookieTimeoutInMinutes),
                    IsPersistent = true,
                    AllowRefresh = false
                });

После завершения входа в систему вы можете получить идентификатор пользователя, как описано в одном вкладыше выше. См. Ответ от Milos Mrdovic выше для более подробных шагов.

var user = User.FindFirst(ClaimTypes.NameIdentifier).Value;

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