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


128

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

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

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

5
MVC 또는 Web APi와 함께 사용 하시겠습니까?
Tushar

답변:


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

2
그것은 동작에서 작동하지만 컨트롤러의 생성자에서 사용하고 싶습니다.
MEHRAN Hafizi

3
수업에서 이것을 사용할 수 있습니까?
Mehran Hafizi

5
ClaimTypes.NameIdentifier현재 사용자 ID를 ClaimTypes.Name제공하고 사용자 이름을 제공합니다.
Nikolay Kostov

3
아무도 UserPrincipal.Current.Name에 무엇이 잘못되었는지 말할 수 있습니까?
tipura

2
@ademcaglin 어떤 이유로 사용자가 null제 경우에 돌아오고 있습니까? .Net core 2.1 Web api그래도 사용 하고 있습니다.
Sruthi Varghese

55

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

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

1
2.0 asp.net 코어의 컨트롤러 내부에 나를 위해 좋은 작품
jmdon

2
_userManager 란 무엇입니까?
NullVoxPopuli

6
ASP.NET Core Identity에서 User Manager는 Dependency Inject에서 사용자를 만들기 위해 제공하는 서비스입니다. 자세한 정보는 문서 참조 :
Ahmad

2
비동기식 방법으로 어떻게이 작업을 수행 할 수 있습니까?
T3.0

나를 위해 null을 반환합니다. 왜?
Alberto Cláudio Mandlate 2019

22

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라는 컨트롤러로 이동합니다. 둘 다 기다리지 않고 작동하지 않습니다 (컴파일하지 않음);)


이것은 정체성의 사용이 필요합니다
Fraze

1
ApplicationUser 란 무엇입니까?
Mike

ApplicationUser는 일반적으로 IdentityUser에서 상속되므로 추가 속성 등으로 확장 할 수 있습니다.
Corgalore

20

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가 인터페이스를 보증하지 않는 특수한 '컬렉션'이라고 결정했다고 가정 합니다.


2
이를 통해 현재 사용자를 애플리케이션의 어느 곳에 나 주입 할 수 있습니다. 훌륭한 답변입니다!
Machado

1
이것은 작동하지 않습니다. 나는 항상 null주사를 얻 습니다 IPrincipal. 또한 임시 서비스를 …GetService<IHttpContextAccessor>()?.HttpContext.User…(와 함께 ?) 추가해야 했는데 그렇지 않으면 충돌이 발생하기 때문입니다 (GetService가 null을 반환했습니다).
ygoe

services.AddTransient(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);HttpContext.User가 ClaimsPrincipal이므로 할 수 있습니다 .
Jay Zelos

18

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

public string LoggedInUser => User.Identity.Name;

적어도 Controller


4
암시 적으로 'System.Security.Principal.IIdentity'형식을 '문자열'로 변환 할 수 없습니다.
Anthony Huang

3
string LoggedInUser = User.Identity.Name;
Alic W

5
이전에 이와 같이 =>사용 된 연산자를 본 적이없는 사람으로서 "표현 체 정의"라고하며이 문서에 설명되어 있습니다 . 나와 같은 미래의 사람들이 궁금해 할 경우를 대비해서.
Nathan Clement

코드는 아마도로부터 변환이 없다는 것을 주어, 편집 이전에 컴파일되지 수 IIdentitystring또한 상단의 코멘트에 명시된 바와 같이. 편집은 단순히 그것을 수정했습니다. 어떻게 결론에 도달했는지 잘 모르겠습니다 (특히 "편집자"점수는 평판이 2 천 미만인 사용자에게만 주어지기 때문에).
fuglede

9

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

  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입니다 (예 : 도메인 \ 사용자 이름).


4

내 문제는 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>

로드 할 탐색 속성을 얻는 방법에 대한 아이디어 (내 ApplicationUser 클래스에있는 회사 탐색 속성의 회사 이름). 탐색 속성을 포함하는 방법을 찾지 못했습니다.
헌터 넬슨

1

기존 답변 외에도 UserID등 사용자 관련 데이터를 보유하는 앱 전체에서 사용 가능한 클래스 인스턴스를 가질 수 있음을 추가하고 싶습니다 .

예를 들어 리팩토링에 유용 할 수 있습니다 . UserID모든 컨트롤러 작업 을 가져오고 UserID서비스 계층과 관련된 모든 메서드에서 추가 매개 변수를 선언 하고 싶지는 않습니다 .

나는 조사를했고 여기에 내 게시물이 있습니다.

속성 DbContext을 추가하여 파생 된 클래스를 확장하거나이 UserId속성이있는 사용자 지정 Session클래스를 구현하기 만하면 됩니다.

필터 수준에서 클래스 인스턴스를 가져오고 UserId값을 설정할 수 있습니다.

그 후에 인스턴스를 삽입 할 때마다 필요한 데이터를 갖게됩니다 (수명은 요청 당 이어야 하므로 AddScoped메소드를 사용하여 등록합니다 ).

작업 예 :

public class AppInitializationFilter : IAsyncActionFilter
{
    private DBContextWithUserAuditing _dbContext;

    public AppInitializationFilter(
        DBContextWithUserAuditing dbContext
        )
    {
        _dbContext = dbContext;
    }

    public async Task OnActionExecutionAsync(
        ActionExecutingContext context,
        ActionExecutionDelegate next
        )
    {
        string userId = null;
        int? tenantId = null;

        var claimsIdentity = (ClaimsIdentity)context.HttpContext.User.Identity;

        var userIdClaim = claimsIdentity.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
        if (userIdClaim != null)
        {
            userId = userIdClaim.Value;
        }

        var tenantIdClaim = claimsIdentity.Claims.SingleOrDefault(c => c.Type == CustomClaims.TenantId);
        if (tenantIdClaim != null)
        {
            tenantId = !string.IsNullOrEmpty(tenantIdClaim.Value) ? int.Parse(tenantIdClaim.Value) : (int?)null;
        }

        _dbContext.UserId = userId;
        _dbContext.TenantId = tenantId;

        var resultContext = await next();
    }
}

자세한 내용은 내 대답을 참조하십시오 .


0

복용 IdentityUser도 효과가 있습니다. 이것은 현재 사용자 개체이며 사용자의 모든 값을 검색 할 수 있습니다.

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

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

0

scafolded Identity 를 사용하고 Asp.net Core 2.2 이상을 사용하는 경우 다음 과 같은보기에서 현재 사용자에 액세스 할 수 있습니다.

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

 @if (SignInManager.IsSignedIn(User))
    {
        <p>Hello @User.Identity.Name!</p>
    }
    else
    {
        <p>You're not signed in!</p>
    }

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


0

이것은 오래된 질문이지만 제 경우는 제 사건이 여기서 논의되지 않았 음을 보여줍니다.

나는 Simon_Weaver ( https://stackoverflow.com/a/54411397/2903893 ) 의 대답을 가장 좋아합니다 . 그는 IPrincipal 및 IIdentity를 사용하여 사용자 이름을 얻는 방법을 자세히 설명합니다. 이 대답은 절대적으로 정확하며이 방법을 사용하는 것이 좋습니다. 그러나 디버깅 중에 ASP.NET이 서비스 원칙을 제대로 채울 수없는 문제가 발생했습니다 . (또는 즉, IPrincipal.Identity.Name이 null입니다)

사용자 이름을 가져 오려면 MVC 프레임 워크가 어딘가에서 가져와야합니다. .NET 세계에서 ASP.NET 또는 ASP.NET Core는 Open ID Connect 미들웨어를 사용합니다. 간단한 시나리오에서 웹 앱은 웹 브라우저에서 사용자를 인증합니다. 이 시나리오에서 웹 애플리케이션은 사용자의 브라우저에 Azure AD에 로그인하도록 지시합니다. Azure AD는 보안 토큰의 사용자에 대한 클레임을 포함하는 사용자의 브라우저를 통해 로그인 응답을 반환합니다. 애플리케이션의 코드에서 작동하도록하려면 웹 앱이 로그인을 위임하는 권한을 제공해야합니다. 웹앱을 Azure 서비스에 배포 할 때이 요구 사항을 충족하는 일반적인 시나리오는 웹앱을 구성하는 것입니다. "앱 서비스"-> YourApp-> "인증 / 승인"블레이드-> "앱 서비스 인증"= "켜기"https://github.com/Huachao/azure-content/blob/master/articles/app-service-api/app-service-api-authentication.md ). 이 프로세스의 내부에서 마법사가 다음 단락에서 보여주는 것과 동일한 설정을 추가하여이 웹 앱의 "부모"웹 구성을 조정한다고 믿습니다 (이것이 제 추측입니다). 기본적으로이 접근 방식이 ASP.NET Core에서 작동하지 않는 이유는 "부모"컴퓨터 구성이 webconfig에서 무시되기 때문입니다. (이것은 100 % 확실하지 않습니다. 제가 가지고있는 가장 좋은 설명을 제공합니다). 따라서 작동하려면 앱에서 수동으로 설정해야합니다.

다음은 Azure AD를 사용하도록 앱을 여러 번 설정하는 방법을 설명하는 문서입니다. https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/aspnetcore2-2

1 단계 : Azure AD 테넌트에 샘플을 등록합니다. (분명합니다. 설명에 시간을 낭비하고 싶지 않습니다).

2 단계 : appsettings.json 파일에서 ClientID 값을 1 단계의 애플리케이션 등록 포털에 등록한 애플리케이션의 애플리케이션 ID로 바꿉니다. TenantId 값을 common으로 바꿉니다.

3 단계 : Startup.cs 파일을 열고 ConfigureServices 메서드에서 .AddAzureAD가 포함 된 줄 뒤에 다음 코드를 삽입합니다. 그러면 응용 프로그램이 Azure AD v2.0 끝점 (즉, 회사 및 학교)으로 사용자를 로그인 할 수 있습니다. Microsoft 개인 계정.

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
    options.Authority = options.Authority + "/v2.0/";
    options.TokenValidationParameters.ValidateIssuer = false;
});

요약 : 토픽 스타터가 설명하는 오류로 이어질 수있는 문제를 한 가지 더 보여 드렸습니다. 이 문제의 원인은 Azure AD (Open ID 미들웨어)에 대한 구성이 누락 되었기 때문입니다. 이 문제를 해결하기 위해 수동으로 "인증 / 인증"설정을 제안합니다. 이를 설정하는 방법에 대한 간략한 개요가 추가되었습니다.


0

대부분의 답변 HttpContext은 문서에서 가장 잘 처리하는 방법을 보여줍니다 .

디버깅 할 때 프로젝트 설정을 확인하고 싶다고 말하고 싶었습니다 Enable Anonymous Authentication = true. 기본값은 .


-1

나는 내 해결책을 얻었다

var claim = HttpContext.User.CurrentUserID();

public static class XYZ
{
    public static int CurrentUserID(this ClaimsPrincipal claim)
    {
        var userID = claimsPrincipal.Claims.ToList().Find(r => r.Type == 
         "UserID").Value;
        return Convert.ToInt32(userID);
    }
    public static string CurrentUserRole(this ClaimsPrincipal claim)
    {
        var role = claimsPrincipal.Claims.ToList().Find(r => r.Type == 
        "Role").Value;
        return role;
    }
}

1
이 코드는 질문에 답할 수 있지만 문제를 해결하는 방법이유 에 대한 추가 컨텍스트를 제공 하면 답변의 장기적인 가치가 향상됩니다.
Alexander
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.