ฉันต้องบอกว่าฉันค่อนข้างแปลกใจที่ HttpContext เป็นโมฆะภายในตัวสร้าง ฉันแน่ใจว่าเป็นเพราะเหตุผลด้านประสิทธิภาพ ได้รับการยืนยันว่าการใช้IPrincipalตามที่อธิบายไว้ด้านล่างจะทำให้มันถูกฉีดเข้าไปในตัวสร้าง โดยพื้นฐานแล้วมันทำเช่นเดียวกับคำตอบที่ยอมรับ แต่ในทางอินเตอร์เฟสมากกว่า
สำหรับใครก็ตามที่พบคำถามนี้กำลังมองหาคำตอบทั่วไป"How to get current user?" คุณก็สามารถเข้าถึงได้โดยตรงจาก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แสดงถึงผู้ใช้และชื่อผู้ใช้ วิกิพีเดียจะปลอบคุณถ้า 'หลัก' เสียงแปลก ๆ
สำคัญที่ต้องตระหนักว่าไม่ว่าคุณจะได้รับจากIHttpContextAccessor.HttpContext.User, ControllerBase.UserหรือControllerBase.HttpContext.Userคุณกำลังได้รับวัตถุที่รับประกันได้ว่าจะหนึ่งClaimsPrincipalIPrincipalวัตถุซึ่งการดำเนินการ
ไม่มีผู้ใช้ประเภทอื่นที่ ASP.NET ใช้Userในขณะนี้ (แต่ไม่ได้หมายความว่าอย่างอื่นไม่สามารถใช้งานได้IPrincipal)
ดังนั้นถ้าคุณมีบางสิ่งบางอย่างที่มีการพึ่งพาของ 'ชื่อผู้ใช้ปัจจุบันที่คุณต้องการฉีดที่คุณควรจะฉีดและไม่แน่นอนIPrincipalIHttpContextAccessor
สำคัญ:อย่าเสียเวลาฉีดยา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เป็นเพียง 'คอลเลกชัน' พิเศษที่ไม่รับประกันอินเทอร์เฟซ