[C#] asp.net 코어에서 현재 사용자를 얻는 방법

이메일과 같은 사용자의 정보를 얻기 위해 현재 사용자를 얻고 싶습니다. 하지만 asp.net 코어에서는 그렇게 할 수 없습니다. 나는 너무 혼란스러워 이것은 내 코드입니다.

HttpContext컨트롤러 생성자 에서 거의 null입니다 . 각 작업에서 사용자를 확보하는 것은 좋지 않습니다. 사용자 정보를 한 번만 받아 다음으로 설정하고 싶습니다 ViewData.

public DashboardController()
{
    var user = HttpContext.User.GetUserId();
}



답변

User.FindFirst(ClaimTypes.NameIdentifier).Value

생성자 편집

아래 코드가 작동합니다.

public Controller(IHttpContextAccessor httpContextAccessor)
{
    var userId = httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value
}

RTM 편집

등록해야합니다 IHttpContextAccessor:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
    }


답변

작동하는 간단한 방법과 나는 확인했습니다.

private readonly UserManager<IdentityUser> _userManager;
public CompetitionsController(UserManager<IdentityUser> userManager)
{
    _userManager = userManager;
}

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

그런 다음이 변수의 모든 속성을 user.Email. 나는 이것이 누군가를 도울 수 있기를 바랍니다.

편집 :

ASP.NET Core에서 다양한 유형의 인증 시스템을 사용하는 것은 분명히 간단하지만 약간 복잡한 원인입니다. 나는 일부 사람들이 받고 있기 때문에 업데이트 null합니다.

JWT 인증의 경우 (ASP.NET Core v3.0.0-preview7에서 테스트 됨) :

var email = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;

var user = await _userManager.FindByEmailAsync(email);


답변

Asp.NET Core에서 현재 사용자를 얻는 다른 방법이 있습니다-여기 어딘가에서 본 것 같습니다 ^^

// Stores UserManager
private readonly UserManager<ApplicationUser> _manager;

// Inject UserManager using dependency injection.
// Works only if you choose "Individual user accounts" during project creation.
public DemoController(UserManager<ApplicationUser> manager)
{
    _manager = manager;
}

// You can also just take part after return and use it in async methods.
private async Task<ApplicationUser> GetCurrentUser()
{
    return await _manager.GetUserAsync(HttpContext.User);
}

// Generic demo method.
public async Task DemoMethod()
{
    var user = await GetCurrentUser();
    string userEmail = user.Email; // Here you gets user email 
    string userId = user.Id;
}  

이 코드는 DemoController라는 컨트롤러로 이동합니다. 둘 다 기다리지 않고 작동하지 않습니다 (컴파일하지 않음);)


답변

HttpContext가 생성자 내부에서 null이라는 사실에 꽤 놀랐습니다. 나는 그것이 성능상의 이유라고 확신합니다. IPrincipal아래 설명 된대로 사용 하면 생성자에 주입 되는지 확인했습니다 . 본질적으로 받아 들여지는 대답과 동일하지만 더 인터페이스 방식으로 수행됩니다.


이 질문을 찾는 사람은 일반적인 “현재 사용자를 얻는 방법” 에 대한 답변을 찾고 있습니다.User에서 직접 액세스 할 수 있습니다 Controller.User. 그러나이 작업은 액션 메서드 내에서만 수행 할 수 있습니다 (컨트롤러가 HttpContexts 및 성능상의 이유로 만 실행되지 않기 때문에 가정합니다).

그러나-생성자에서 필요하거나 (OP처럼) 현재 사용자가 필요한 다른 주입 가능한 개체를 만들어야하는 경우 아래 방법이 더 나은 방법입니다.

IPrincipal을 주입하여 사용자 가져 오기

먼저 충족 IPrincipalIIdentity

public interface IPrincipal
{
    IIdentity Identity { get; }
    bool IsInRole(string role);
}

public interface IIdentity
{
    string AuthenticationType { get; }
    bool IsAuthenticated { get; }
    string Name { get; }
}

IPrincipalIIdentity사용자와 사용자 이름을 나타냅니다. Wikipedia는 ‘Principal’이 이상하게 들리면 위로 할 것 입니다.

중요 실현하기 위해 당신이 그것을에서 얻을 여부 IHttpContextAccessor.HttpContext.User, ControllerBase.User또는 ControllerBase.HttpContext.User당신이있어 이 보장되는 객체 받고 ClaimsPrincipal있는 구현 객체를IPrincipal .

현재 ASP.NET이 사용하는 다른 유형의 사용자는 User없습니다 (그러나 다른 것이 구현할 수 없다는 것은 아닙니다 IPrincipal).

그래서 당신은 당신이 당신이 주입되어야 주입하려는 ‘현재 사용자 이름’의 종속성 무언가가 있다면 IPrincipal확실히하지 IHttpContextAccessor.

중요 :IPrincipal 컨트롤러 또는 작업 방법에 직접 주입 하는 데 시간을 낭비하지 마십시오 User. 이미 거기에서 사용할 수 있으므로 의미 가 없습니다.

에서 startup.cs:

   // Inject IPrincipal
   services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);

그런 다음 사용자가 필요한 DI 개체 IPrincipal에서 현재 사용자를 가져 오기 위해 주입 하기 만하면 됩니다.

당신이 단위 테스트 당신이 보낼 필요가 없습니다하고 있다면 여기서 가장 중요한 것은 HttpContext있지만 나타내는 모의 뭔가가 필요 IPrincipal 단지가 될 수있는가 ClaimsPrincipal .

내가 100 % 확신하지 못하는 한 가지 더 중요한 것. 당신이 실제 요구에 액세스해야하는 경우에서 ClaimsPrincipal당신은 캐스트 필요 IPrincipalClaimsPrincipal. 이것은 우리가 런타임에 그것이 그 유형이라는 것을 100 % 알고 있기 때문에 괜찮습니다 HttpContext.User. 실제로 생성자에서이 작업을 수행하는 것을 좋아 IPrincipal 합니다.ClaimsPrincipal ..

조롱을하는 경우 에는 ClaimsPrincipal직접 생성 하여 어떤 테이크에 전달해도됩니다 IPrincipal.

정확히 왜 인터페이스가 없는지 IClaimsPrincipal잘 모르겠습니다. 나는 MS ClaimsPrincipal가 인터페이스를 보증하지 않는 특수한 ‘컬렉션’이라고 결정했다고 가정 합니다.


답변

현재 (2017 년 4 월) 현재 다음 사항이 작동하는 것으로 보입니다.

public string LoggedInUser => User.Identity.Name;

적어도 Controller


답변

아마도 나는 대답을 보지 못했지만 이것이 내가하는 방법입니다.

  1. .Net Core-> 속성-> launchSettings.json

이 값을 변경해야합니다.

"windowsAuthentication": true, // needs to be true
"anonymousAuthentication": false,  // needs to be false 

Startup.cs-> ConfigureServices (…)

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

MVC 또는 Web Api 컨트롤러

private readonly IHttpContextAccessor _httpContextAccessor;
//constructor then
_httpContextAccessor = httpContextAccessor;

컨트롤러 방법 :

string userName = _httpContextAccessor.HttpContext.User.Identity.Name;

결과는 userName입니다 (예 : 도메인 \ 사용자 이름).


답변

내 문제는 cshtml 파일의 개체로 로그인 한 사용자에 액세스하는 것이 었습니다. ViewData에서 사용자를 원했다면이 접근 방식이 도움이 될 수 있습니다.

cshtml 파일에서

@using Microsoft.AspNetCore.Identity
@inject UserManager<ApplicationUser> UserManager

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>
    @UserManager.FindByNameAsync(UserManager.GetUserName(User)).Result.Email
    </title>
  </head>
  <body>

  </body>
</html>