ครั้งหนึ่งฉันเคยสร้างบัญชีโดเมนชุดหนึ่งด้วยกล่องจดหมายโดยใช้โปรแกรม windows ได้สำเร็จ อย่างไรก็ตาม เมื่อฉันให้รหัสนี้แก่เพื่อนร่วมงานคนหนึ่งของฉัน (เธอรับผิดชอบในการพัฒนาแอปพลิเคชันเว็บ) และย้ายไปยัง asp.net ก็ทำได้เพียงสร้างโดเมนเท่านั้น บัญชี ไม่สามารถสร้างกล่องจดหมายได้ ทำไม
เราได้ปรึกษาวิศวกรของ Microsoft และเขาบอกเราว่านี่เป็นเพราะสิทธิ์ของ asp.net ไม่เพียงพอ เราควรจำลองผู้ใช้ใน asp.net เพื่อให้สามารถสร้างได้สำเร็จ
ฉันคัดลอกบทความที่เกี่ยวข้องจาก Microsoft:
เลียนแบบบัญชีหรือผู้ใช้ที่ได้รับการรับรองความถูกต้องของ IIS
เมื่อต้องการเลียนแบบผู้ใช้ที่ได้รับการรับรองความถูกต้องของ Microsoft Internet Information Services (IIS) เมื่อได้รับทุกคำขอสำหรับทุกเพจในแอปพลิเคชัน ASP.NET คุณต้องรวมไว้ในไฟล์ Web.config สำหรับแท็ก <identity> ของแอปพลิเคชันนี้ และตั้งค่าแอตทริบิวต์การปลอมตัวเป็นจริง ตัวอย่างเช่น:
<identity impersonate="true" />
การเลียนแบบผู้ใช้เฉพาะสำหรับการร้องขอทั้งหมดไปยังแอปพลิเคชัน ASP.NET
เมื่อต้องการเลียนแบบผู้ใช้เฉพาะสำหรับการร้องขอทั้งหมดบนเพจทั้งหมดของแอปพลิเคชัน ASP.NET คุณสามารถระบุแอตทริบิวต์ชื่อผู้ใช้และรหัสผ่านได้ ตัวอย่างเช่น:
<identity impersonate="true" userName="accountname" pass="password" />
หมายเหตุ: ข้อมูลประจำตัวของกระบวนการที่เลียนแบบผู้ใช้เฉพาะบนเธรดต้องมีสิทธิ์ "เป็นส่วนหนึ่งของระบบปฏิบัติการ" ตามค่าเริ่มต้น กระบวนการ Aspnet_wp.exe ทำงานภายใต้บัญชีคอมพิวเตอร์ชื่อ ASPNET อย่างไรก็ตาม บัญชีนี้ไม่มีสิทธิ์ที่จำเป็นในการแอบอ้างเป็นผู้ใช้รายใดรายหนึ่ง หากคุณพยายามแอบอ้างเป็นผู้ใช้รายใดรายหนึ่ง ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้น
เมื่อต้องการแก้ไขปัญหานี้ ให้ใช้วิธีใดวิธีหนึ่งต่อไปนี้:
•
ให้สิทธิ์บัญชี ASPNET (บัญชีที่มีสิทธิ์การใช้งานน้อยที่สุด) "ทำหน้าที่เป็นส่วนหนึ่งของระบบปฏิบัติการ"
หมายเหตุ: แม้ว่าวิธีนี้อาจช่วยแก้ปัญหาได้ แต่ Microsoft ไม่แนะนำวิธีนี้
•
ในส่วนการกำหนดค่า <processModel> ของไฟล์ Machine.config ให้เปลี่ยนบัญชีที่กระบวนการ Aspnet_wp.exe รันไปยังบัญชีระบบ
การแอบอ้างเป็นผู้ใช้ที่ได้รับการรับรองความถูกต้องในโค้ด
หากต้องการเลียนแบบผู้ใช้ที่ได้รับการรับรองความถูกต้อง (User.Identity) เฉพาะเมื่อเรียกใช้โค้ดบางส่วนเท่านั้น คุณสามารถใช้โค้ดต่อไปนี้ได้ วิธีการนี้กำหนดให้ ID ผู้ใช้การรับรองความถูกต้องเป็นประเภท WindowsIdentity
Visual Basic .NET
Dim impersonationContext เป็น System.Security.Principal.WindowsImpersonationContext
หรี่ปัจจุบัน WindowsIdentity เป็น System.Security.Principal.WindowsIdentity
ปัจจุบัน WindowsIdentity = CType (User.Identity, System.Security.Principal.WindowsIdentity)
impersonationContext = ปัจจุบัน WindowsIdentity.Impersonate ()
'ใส่รหัสของคุณที่ทำงานภายใต้บริบทด้านความปลอดภัยของผู้ใช้ที่ตรวจสอบความถูกต้องที่นี่
การเลียนแบบ Context.Undo()
Visual C# .NET
System.Security.Principal.WindowsImpersonationContext การเลียนแบบ Context;
การเลียนแบบบริบท =
((System.Security.Principal.WindowsIdentity) User.Identity). เลียนแบบ ();
//ใส่รหัสของคุณที่ทำงานภายใต้บริบทด้านความปลอดภัยของผู้ใช้ที่ตรวจสอบสิทธิ์ที่นี่
การเลียนแบบ Context.Undo();
Visual J # .NET
System.Security.Principal.WindowsImpersonationContext การเลียนแบบ Context;
การเลียนแบบบริบท =
((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).เลียนแบบ();
//ใส่รหัสของคุณที่ทำงานภายใต้บริบทด้านความปลอดภัยของผู้ใช้ที่ตรวจสอบสิทธิ์ที่นี่
การเลียนแบบ Context.Undo();
การแอบอ้างเป็นผู้ใช้ที่ระบุในโค้ด
เมื่อต้องการแอบอ้างเป็นผู้ใช้เฉพาะเมื่อเรียกใช้โค้ดบางส่วนเท่านั้น ให้ใช้โค้ดต่อไปนี้:
Visual Basic .NET
<%@ Page Language="VB" %>
<%@ นำเข้าเนมสเปซ = "System.Web" %>
<%@ นำเข้าเนมสเปซ = "System.Web.Security" %>
<%@ นำเข้าเนมสเปซ = "System.Security.Principal" %>
<%@ นำเข้าเนมสเปซ = "System.Runtime.InteropServices" %>
<สคริปต์ runat=เซิร์ฟเวอร์>
หรี่ LOGON32_LOGON_INTERACTIVE เป็นจำนวนเต็ม = 2
หรี่ LOGON32_PROVIDER_DEFAULT เป็นจำนวนเต็ม = 0
Dim ImpersonationContext As WindowsImpersonationContext
ประกาศฟังก์ชัน LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _
ByVal lpszDomain เป็นสตริง _
ByVal lpszPassword เป็นสตริง, _
ByVal dwLogonType เป็นจำนวนเต็ม _
ByVal dwLogonProvider เป็นจำนวนเต็ม _
ByRef phToken As IntPtr) เป็นจำนวนเต็ม
ประกาศฟังก์ชันอัตโนมัติ DuplicateToken Lib "advapi32.dll" ( _
ByVal TokenHandle ที่มีอยู่เป็น IntPtr, _
ByVal ImpersonationLevel เป็นจำนวนเต็ม _
ByRef DuplicateTokenHandle As IntPtr) เป็นจำนวนเต็ม
ประกาศฟังก์ชั่นอัตโนมัติ RevertToSelf Lib "advapi32.dll" () ตราบใดที่
ประกาศฟังก์ชั่นอัตโนมัติ CloseHandle Lib "kernel32.dll" (ByVal จัดการเป็น IntPtr) ตราบใดที่
Page_Load ย่อยสาธารณะ (ByVal เป็นวัตถุ ByVal e As EventArgs)
ถ้า impersonateValidUser("username", "domain", "password") จากนั้น
'ใส่รหัสของคุณที่ทำงานภายใต้บริบทด้านความปลอดภัยของผู้ใช้เฉพาะที่นี่
ยกเลิกการเลียนแบบ()
อื่น
'การแอบอ้างบุคคลอื่นของคุณล้มเหลว ดังนั้น รวมกลไกป้องกันความผิดพลาดไว้ที่นี่
สิ้นสุดถ้า
จบหมวดย่อย
ฟังก์ชั่นส่วนตัว impersonateValidUser (ชื่อผู้ใช้ ByVal As String, _
โดเมน ByVal เป็นสตริง, รหัสผ่าน ByVal เป็นสตริง) เป็นบูลีน
Dim tempWindowsIdentity เป็น WindowsIdentity
โทเค็น Dim As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = เท็จ
ถ้า RevertToSelf() แล้ว
ถ้า LogonUserA (ชื่อผู้ใช้, โดเมน, รหัสผ่าน, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT โทเค็น) <> 0 จากนั้น
ถ้า DuplicateToken(token, 2, tokenDuplicate) <> 0 จากนั้น
tempWindowsIdentity = WindowsIdentity ใหม่ (tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
ถ้าไม่ใช่การแอบอ้างบริบทก็ไม่มีอะไรแล้ว
impersonateValidUser = จริง
สิ้นสุดถ้า
สิ้นสุดถ้า
สิ้นสุดถ้า
สิ้นสุดถ้า
ถ้าไม่ใช่ tokenDuplicate.Equals(IntPtr.Zero) แล้ว
CloseHandle (โทเค็นซ้ำ)
สิ้นสุดถ้า
ถ้าไม่ใช่ token.Equals(IntPtr.Zero) แล้ว
CloseHandle (โทเค็น)
สิ้นสุดถ้า
ฟังก์ชันสิ้นสุด
ยกเลิกการเลียนแบบส่วนตัวย่อย ()
การเลียนแบบ Context.Undo()
จบหมวดย่อย
</script>
Visual C# .NET
<%@ ภาษาเพจ = "C#"%>
<%@ นำเข้าเนมสเปซ = "System.Web" %>
<%@ นำเข้าเนมสเปซ = "System.Web.Security" %>
<%@ นำเข้าเนมสเปซ = "System.Security.Principal" %>
<%@ นำเข้าเนมสเปซ = "System.Runtime.InteropServices" %>
<สคริปต์ runat=เซิร์ฟเวอร์>
สาธารณะ int LOGON32_LOGON_INTERACTIVE = 2;
สาธารณะ int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext การเลียนแบบ Context;
[DllImport("advapi32.dll")]
สาธารณะคงที่ภายนอก int LogonUserA (สตริง lpszUserName,
สตริง lpszDomain,
สตริง lpszPassword,
int dwLogonType,
int dwLogonProvider,
อ้างอิง IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
สาธารณะคงที่ภายนอก int DuplicateToken (IntPtr hToken,
ระดับการเลียนแบบ int,
อ้างอิง IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
บูลภายนอกแบบคงที่สาธารณะ RevertToSelf ();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
บูลภายนอกแบบคงที่สาธารณะ CloseHandle (ตัวจัดการ IntPtr);
โมฆะสาธารณะ Page_Load (วัตถุ s, EventArgs e)
-
if(impersonateValidUser("ชื่อผู้ใช้", "โดเมน", "รหัสผ่าน"))
-
//ใส่โค้ดของคุณที่ทำงานภายใต้บริบทด้านความปลอดภัยของผู้ใช้รายใดรายหนึ่งที่นี่
ยกเลิกการเลียนแบบ();
-
อื่น
-
//การแอบอ้างบุคคลอื่นของคุณล้มเหลว ดังนั้น โปรดรวมกลไกป้องกันข้อผิดพลาดไว้ที่นี่
-
-
บูลส่วนตัว impersonateValidUser (ชื่อผู้ใช้สตริง, โดเมนสตริง, รหัสผ่านสตริง)
-
WindowsIdentity อุณหภูมิ WindowsIdentity;
โทเค็น IntPtr = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.ศูนย์;
ถ้า(RevertToSelf())
-
ถ้า (LogonUserA (ชื่อผู้ใช้, โดเมน, รหัสผ่าน, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT โทเค็นอ้างอิง) != 0)
-
ถ้า (DuplicateToken (โทเค็น, 2, อ้างอิง tokenDuplicate) != 0)
-
tempWindowsIdentity = WindowsIdentity ใหม่ (tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
ถ้า (impersonationContext != null)
-
CloseHandle(โทเค็น);
CloseHandle (โทเค็นซ้ำ);
กลับเป็นจริง;
-
-
-
-
ถ้า (โทเค็น! = IntPtr.Zero)
CloseHandle(โทเค็น);
ถ้า (tokenDuplicate! = IntPtr.Zero)
CloseHandle (โทเค็นซ้ำ);
กลับเท็จ;
-
โมฆะส่วนตัว undoImpersonation()
-
การเลียนแบบ Context.Undo();
-
</script>
Visual J# .NET
<%@ ภาษาเพจ = "VJ#" %>
<%@ นำเข้าเนมสเปซ = "System.Web" %>
<%@ นำเข้าเนมสเปซ = "System.Web.Security" %>
<%@ นำเข้าเนมสเปซ = "System.Security.Principal" %>
<%@ นำเข้าเนมสเปซ = "System.Runtime.InteropServices" %>
<สคริปต์ runat=เซิร์ฟเวอร์>
int สาธารณะคงที่ LOGON32_LOGON_INTERACTIVE = 2;
int สาธารณะคงที่ LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext การเลียนแบบ Context;
/** @attribute DllImport("advapi32.dll") */
สาธารณะคงที่ดั้งเดิม int LogonUserA (สตริง lpszUserName,
สตริง lpszDomain,
สตริง lpszPassword,
int dwLogonType,
int dwLogonProvider,
System.IntPtr[] phToken);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto, SetLastError=true) */
สาธารณะคงพื้นเมือง int DuplicateToken (System.IntPtr hToken,
ระดับการเลียนแบบ int,
System.IntPtr[] hNewToken);
/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */
CloseHandle ดั้งเดิมแบบคงที่สาธารณะ (ตัวจัดการ System.IntPtr []);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto,SetLastError=true) */
บูลีนดั้งเดิมแบบคงที่สาธารณะ RevertToSelf ();
โมฆะสาธารณะ Page_Load (วัตถุ s, System.EventArgs e)
-
if(impersonateValidUser("ชื่อผู้ใช้", "โดเมน", "รหัสผ่าน"))
-
//ใส่โค้ดของคุณที่ทำงานภายใต้บริบทด้านความปลอดภัยของผู้ใช้รายใดรายหนึ่งที่นี่
ยกเลิกการเลียนแบบ();
-
อื่น
-
//การแอบอ้างบุคคลอื่นของคุณล้มเหลว ดังนั้น โปรดรวมกลไกป้องกันข้อผิดพลาดไว้ที่นี่
-
-
ส่วนตัวบูลีน impersonateValidUser (ชื่อผู้ใช้สตริง, โดเมนสตริง, รหัสผ่านสตริง)
-
WindowsIdentity อุณหภูมิ WindowsIdentity;
โทเค็น System.IntPtr[] = System.IntPtr[1] ใหม่;
System.IntPtr[] tokenDuplicate = System.IntPtr[1] ใหม่;
ถ้า(RevertToSelf())
-
ถ้า (LogonUserA (ชื่อผู้ใช้, โดเมน, รหัสผ่าน, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT โทเค็น) != 0)
-
ถ้า (DuplicateToken (โทเค็น [0], 2, tokenDuplicate) != 0)
-
tempWindowsIdentity = WindowsIdentity ใหม่ (tokenDuplicate[0]);
impersonationContext = tempWindowsIdentity.Impersonate();
ถ้า (impersonationContext != null)
-
CloseHandle(โทเค็นซ้ำ);
CloseHandle(โทเค็น);
กลับเป็นจริง;
-
-
-
-
ถ้า(!token[0].เท่ากับ(System.IntPtr.Zero))
CloseHandle(โทเค็น);
ถ้า(!tokenDuplicate[0].เท่ากับ(System.IntPtr.Zero))
CloseHandle (โทเค็นซ้ำ);
กลับเท็จ;
-
โมฆะส่วนตัว undoImpersonation()
-
การเลียนแบบ Context.Undo();
-
</สคริปต์>
หมายเหตุ: ข้อมูลประจำตัวของกระบวนการที่เลียนแบบผู้ใช้เฉพาะบนเธรดต้องมีสิทธิ์ "เป็นส่วนหนึ่งของระบบปฏิบัติการ" ตามค่าเริ่มต้น กระบวนการ Aspnet_wp.exe ทำงานภายใต้บัญชีคอมพิวเตอร์ชื่อ ASPNET อย่างไรก็ตาม บัญชีนี้ไม่มีสิทธิ์ที่จำเป็นในการแอบอ้างเป็นผู้ใช้รายใดรายหนึ่ง หากคุณพยายามแอบอ้างเป็นผู้ใช้รายใดรายหนึ่ง ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้น
เมื่อต้องการแก้ไขปัญหานี้ ให้ใช้วิธีใดวิธีหนึ่งต่อไปนี้:
•
ให้สิทธิ์ "ทำหน้าที่เป็นส่วนหนึ่งของระบบปฏิบัติการ" แก่บัญชี ASPNET
•
ในส่วนการกำหนดค่า <processModel> ของไฟล์ Machine.config ให้เปลี่ยนบัญชีที่กระบวนการ Aspnet_wp.exe รันไปยังบัญชีระบบ