ฉันต้องบอกว่าฉันค่อนข้างแปลกใจที่ 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
คุณกำลังได้รับวัตถุที่รับประกันได้ว่าจะหนึ่ง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
เป็นเพียง 'คอลเลกชัน' พิเศษที่ไม่รับประกันอินเทอร์เฟซ