ในแอปพลิเคชัน MVC-5 ของฉัน ฉันกำลังเพิ่ม/แก้ไขผู้ใช้ใน Active Directory ผ่านแอปพลิเคชันของฉัน เมื่อใดก็ตามที่ฉันทำการเปลี่ยนแปลงใน AD ทุกครั้งที่ฉันต้องส่ง ldapUserName(Admin) และ ldapPassword(pass@123) เพื่อเชื่อมต่อกับ Active Directory จากนั้นมีเพียงฉันเท่านั้นที่สามารถดำเนินการใน AD ได้ แทนที่จะส่งข้อมูลประจำตัวแต่ละครั้ง ฉันต้องการใช้บัญชีบริการ (โดเมน\บริการ_บัญชี) ที่แอปพลิเคชันของฉันทำงานอยู่เพื่อเชื่อมต่อกับ AD จะบรรลุสิ่งนั้นได้อย่างไร ??
ต้องการใช้บัญชีบริการเพื่อเชื่อมต่อกับ AD ที่แอปของฉันทำงานอยู่
คำตอบ (2)
เพียงสร้าง DirectoryEntry
โดย new DirectoryEntry(ldabPath, null, null)
จะใช้ข้อมูลประจำตัวของผู้ใช้ปัจจุบัน (บัญชีบริการในกรณีบริการ Windows) คีย์กำลังส่ง null ไปยังทั้งชื่อผู้ใช้และรหัสผ่าน
นั่นคือสิ่งที่คุณต้องการ?
เพียงตรวจสอบให้แน่ใจว่าบัญชีบริการมีสิทธิ์เพียงพอที่จะตั้งรหัสผ่านสำหรับผู้ใช้ทั้งหมดที่เกี่ยวข้อง
คุณสามารถเลือกหนึ่งใน 2 ตัวเลือก
ตัวเลือกที่ 1. คุณเรียกใช้แอปพลิเคชันของคุณบนคอมพิวเตอร์ที่เข้าร่วมกับโดเมนที่คุณเพิ่ม\ลบผู้ใช้ออก ในกรณีนี้ วิธีแก้ไขที่ง่ายที่สุดคือการเรียกใช้แอปพลิเคชันของคุณ (กลุ่มแอปพลิเคชัน) ภายใต้บัญชีโดเมนที่มีสิทธิ์เพียงพอ (ด้วยวิธีง่ายๆ อาจเป็นบัญชีที่อยู่ในกลุ่มผู้ดูแลระบบโดเมน จะเป็นผู้ดูแลระบบบนโฮสต์ที่แอปพลิเคชันทำงานด้วย)
ตัวเลือกที่ 2 คุณเรียกใช้แอปพลิเคชันของคุณบนคอมพิวเตอร์แบบสแตนด์อโลนที่ไม่ได้เข้าร่วมกับโดเมน ในกรณีนี้ คุณสามารถเลือกอย่างใดอย่างหนึ่งต่อไปนี้:
A. เลียนแบบเธรดของคุณเพื่อทำหน้าที่เป็นบัญชีโดเมนเมื่อทำการเชื่อมต่อเครือข่ายทั้งหมด คุณต้องใช้ LogonUser ฟังก์ชั่นพร้อมแฟล็ก LOGON32_LOGON_NEW_CREDENTIALS ข้อเสียเปรียบของวิธีนี้คือการเชื่อมต่อเครือข่ายทั้งหมด (เช่น คุณเชื่อมต่อกับเครือข่ายที่ใช้ร่วมกัน) จะทำภายใต้บัญชีโดเมน หากต้องการรายละเอียดเพิ่มเติมเกี่ยวกับการนำไปใช้ โปรดดูโพสต์นี้
B. สร้างตัวจัดการการเชื่อมต่อซึ่งจะสร้าง DirectoryEntry ให้กับคุณด้วยข้อมูลประจำตัวที่จำเป็น ดูรหัสด้านล่าง:
public interface IDirectoryEntryManager
{
DirectoryEntry GetDirectoryEntry(string domain, string baseDn);
}
public interface ICredentialProvider
{
Credential GetCredential(string domain);
}
public class Credential
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class DirectoryEntryManager : IDirectoryEntryManager, IDisposable
{
private class DomainConnectionInfo
{
internal DomainConnectionInfo(string server, Credential credential)
{
Server = server;
Credential = credential;
}
internal string Server { get; private set; }
internal Credential Credential { get; private set; }
}
private bool disposed;
ICredentialProvider _credentialProvider;
Dictionary<string, DomainConnectionInfo> connectionsInfo = new Dictionary<string, DomainConnectionInfo>(StringComparer.OrdinalIgnoreCase);
Dictionary<string, DirectoryEntry> connections = new Dictionary<string, DirectoryEntry>(StringComparer.OrdinalIgnoreCase);
public DirectoryEntryManager(ICredentialProvider credentialProvider)
{
_credentialProvider = credentialProvider;
}
public DirectoryEntry GetDirectoryEntry(string domain, string baseDn)
{
if (disposed)
{
throw new ObjectDisposedException(this.GetType().Name);
}
return GetOrCreateConnection(domain, baseDn);
}
public void Dispose()
{
if (!disposed)
{
foreach (var connection in connections)
{
connection.Value.Dispose();
}
connections.Clear();
disposed = true;
}
}
private DirectoryEntry GetOrCreateConnection(string domain, string baseDn)
{
DomainConnectionInfo info;
if (!connectionsInfo.TryGetValue(domain, out info))
{
var credential = _credentialProvider.GetCredential(domain);
var dc = DomainController.FindOne(new DirectoryContext(DirectoryContextType.Domain, credential.UserName, credential.Password));
info = new DomainConnectionInfo(dc.Name, credential);
// maintaining a connection to rootDse object to make all LDAP queries use this single connection under the hood. Increasing performance
var entry = new DirectoryEntry(string.Format("LDAP://{0}/RootDSE", dc.Name));
entry.RefreshCache();
connections.Add(domain, entry);
connectionsInfo.Add(domain, info);
}
return new DirectoryEntry(string.Format("LDAP://{0}/{1}", info.Server, baseDn), info.Credential.UserName, info.Credential.Password);
}
}
ไม่ได้ทดสอบรหัส ใช้การผูกเซิร์ฟเวอร์แทนการผูกแบบไร้เซิร์ฟเวอร์ (เช่น LDAP://domain.com) จะดีกว่าในกรณีที่คุณสร้างผู้ใช้ในส่วนหนึ่งของโปรแกรมและพยายามเข้าถึงในส่วนอื่น การใช้ Serverless Bind ทำให้คุณสามารถเชื่อมต่อกับ DC ต่างๆ ได้ ดังนั้นผู้ใช้ที่คุณพยายามเข้าถึงอาจไม่ถูกจำลองแบบไปยัง DC ตัวที่ 2
โปรดทราบว่าตัวควบคุมโดเมนอาจไม่พร้อมใช้งาน ดังนั้นคุณต้องใช้ตรรกะเพื่อค้นหา DC อื่นและรีเฟรชแคชการเชื่อมต่อของคุณหากจำเป็น
คุณสามารถจัดเก็บข้อมูลประจำตัวในไฟล์\LSA ที่อาจเข้ารหัส และทำให้คลาส DirectoryEntryManager เป็นซิงเกิลตัน