HttpContext가 생성자 내부에서 null이라는 사실에 꽤 놀랐습니다. 나는 그것이 성능상의 이유라고 확신합니다. IPrincipal
아래 설명 된대로 사용 하면 생성자에 주입 되는지 확인했습니다 . 본질적으로 받아 들여지는 대답과 동일하지만 더 인터페이스 방식으로 수행됩니다.
이 질문을 찾는 사람은 일반적인 "현재 사용자를 얻는 방법" 에 대한 답변을 찾고 있습니다.User
에서 직접 액세스 할 수 있습니다 Controller.User
. 그러나이 작업은 액션 메서드 내에서만 수행 할 수 있습니다 (컨트롤러가 HttpContexts 및 성능상의 이유로 만 실행되지 않기 때문에 가정합니다).
그러나-생성자에서 필요하거나 (OP처럼) 현재 사용자가 필요한 다른 주입 가능한 개체를 만들어야하는 경우 아래 방법이 더 나은 방법입니다.
IPrincipal을 주입하여 사용자 가져 오기
먼저 충족 IPrincipal
및IIdentity
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}
IPrincipal
및 IIdentity
사용자와 사용자 이름을 나타냅니다. 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
당신은 캐스트 필요 IPrincipal
로 ClaimsPrincipal
. 이것은 우리가 런타임에 그것이 그 유형이라는 것을 100 % 알고 있기 때문에 괜찮습니다 HttpContext.User
. 실제로 생성자에서이 작업을 수행하는 것을 좋아 IPrincipal
합니다.ClaimsPrincipal
..
조롱을하는 경우 에는 ClaimsPrincipal
직접 생성 하여 어떤 테이크에 전달해도됩니다 IPrincipal
.
정확히 왜 인터페이스가 없는지 IClaimsPrincipal
잘 모르겠습니다. 나는 MS ClaimsPrincipal
가 인터페이스를 보증하지 않는 특수한 '컬렉션'이라고 결정했다고 가정 합니다.