Tôi phải nói rằng tôi khá ngạc nhiên rằng HttpContext là null bên trong hàm tạo. Tôi chắc rằng đó là vì lý do hiệu suất. Đã xác nhận rằng việc sử dụng IPrincipalnhư mô tả bên dưới sẽ đưa nó vào hàm tạo. Về cơ bản, nó hoạt động giống như câu trả lời được chấp nhận, nhưng theo một cách giao diện hơn.
Đối với bất kỳ ai tìm thấy câu hỏi này đang tìm kiếm câu trả lời cho câu trả lời chung chung "Làm thế nào để có được người dùng hiện tại?" bạn chỉ có thể truy cập Usertrực tiếp từ Controller.User. Nhưng bạn chỉ có thể thực hiện điều này bên trong các phương thức hành động (tôi giả sử vì bộ điều khiển không chỉ chạy với HttpContexts và vì lý do hiệu suất).
Tuy nhiên - nếu bạn cần nó trong hàm tạo (như OP đã làm) hoặc cần tạo các đối tượng có thể tiêm khác mà cần người dùng hiện tại thì cách tiếp cận dưới đây là tốt hơn:
Tiêm IPrincipal để có được người dùng
Lần đầu gặp gỡ IPrincipalvàIIdentity
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}
IPrincipalvà IIdentityđại diện cho người dùng và tên người dùng. Wikipedia sẽ an ủi bạn nếu 'Hiệu trưởng' nghe có vẻ kỳ quặc .
Quan trọng là phải nhận ra rằng cho dù bạn nhận được nó từ IHttpContextAccessor.HttpContext.User, ControllerBase.Userhoặc ControllerBase.HttpContext.Userbạn đang nhận được một đối tượng mà là đảm bảo được một ClaimsPrincipalđối tượng mà cụIPrincipal .
Không có loại Người dùng nào khác mà ASP.NET sử dụng Userngay bây giờ, (nhưng điều đó không có nghĩa là một cái gì đó khác không thể thực hiện IPrincipal).
Vì vậy, nếu bạn có thứ gì đó phụ thuộc vào 'tên người dùng hiện tại' mà bạn muốn tiêm, bạn nên tiêm IPrincipalvà chắc chắn là không IHttpContextAccessor.
Quan trọng: Đừng lãng phí thời gian tiêm IPrincipaltrực tiếp vào bộ điều khiển hoặc phương pháp hành động của bạn - điều đó là vô nghĩa vì Userbạn đã có sẵn ở đó.
Trong startup.cs:
// Inject IPrincipal
services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
Sau đó, trong đối tượng DI của bạn cần người dùng mà bạn chỉ cần đưa vào IPrincipalđể có được người dùng hiện tại.
Điều quan trọng nhất ở đây là nếu bạn đang thực hiện các bài kiểm tra đơn vị, bạn không cần phải gửi một HttpContext, mà chỉ cần mô phỏng một cái gì đó đại diện cho IPrincipal cái có thể ClaimsPrincipal .
Một điều quan trọng nữa mà tôi không chắc 100%. Nếu bạn cần truy cập các xác nhận quyền sở hữu thực tế từ ClaimsPrincipalbạn cần truyền IPrincipalđến ClaimsPrincipal. Điều này là tốt vì chúng tôi biết 100% rằng trong thời gian chạy nó thuộc loại đó (vì đó là cái gì HttpContext.User). Tôi thực sự thích chỉ làm điều này trong hàm tạo vì tôi đã biết chắc chắn bất kỳ IPrincipal sẽ là a ClaimsPrincipal.
Nếu bạn đang chế nhạo, chỉ cần tạo ClaimsPrincipaltrực tiếp và chuyển nó cho bất cứ điều gì cần thiết IPrincipal.
Chính xác tại sao không có giao diện cho IClaimsPrincipaltôi không chắc chắn. Tôi cho rằng MS đã quyết định rằng đó ClaimsPrincipalchỉ là một 'bộ sưu tập' chuyên biệt không đảm bảo giao diện.