在我的MVC-5应用程序中,我通过我的应用程序添加/编辑活动目录中的用户。每当我在AD中进行更改时,每次我需要传递ldapUserName(Admin)和ldapPassword(传递@ 123)来连接到Active目录。然后我只能在AD中执行操作。每次我想使用服务帐户(domain \ service_account)运行我的应用程序以便连接到AD时,代替传递凭据。如何实现?
答案 0 :(得分:0)
您可以选择以下两个选项之一。
选项1.您在加入域的计算机上运行应用程序,从中添加\删除用户。在这种情况下,最简单的解决方案是在具有足够权限的域帐户下运行您的应用程序(应用程序池)(以简单的方式可以是属于Domain Admins组的帐户。也将是主机上的管理员,应用程序运行的位置)
选项2.您在未加入域的独立计算机上运行应用程序。在这种情况下,您可以选择以下之一:
一个。在执行所有网络连接时,模拟您的线程充当域帐户。您需要使用带有LOGON32_LOGON_NEW_CREDENTIALS标志的LogonUser函数。该方法的缺点是所有网络连接(例如,您连接到网络共享)将在域帐户下进行。有关实施的更多详细信息,请参阅this post。
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)会更好。使用无服务器绑定可以连接到不同的DC,因此您尝试访问的用户可能无法复制到第二个DC。
请注意,域控制器可能不可用,因此您需要实现逻辑,搜索另一个DC并在需要时刷新连接缓存。
您可以将凭证存储在可能已加密的文件\ LSA中,并将DirectoryEntryManager类设为单例。
答案 1 :(得分:0)
只需按DirectoryEntry
创建new DirectoryEntry(ldabPath, null, null)
即可使用当前用户的凭据(如果是Windows服务,则使用服务帐户)。关键是将 null 传递给用户名和密码。
这就是你想要的吗?
只需确保服务帐户有足够的权限为所有相关用户设置密码。