Ответ 1
Я нашел контейнер разделов в CN = Разделы, CN = Конфигурация, которая содержит все домены.
Когда вы сопоставляете пользователя с partion, вы можете прочитать настоящее доменное имя из свойства nETBIOSName + "\" + sAMAccountName.
Как я могу получить пользователя и домен Windows из объекта Active Directory DirectoryEntry (SchemaClassName = "user" )?
Имя пользователя находится в свойстве sAMAccountName, но где я могу найти доменное имя?
(Я не могу предположить фиксированное имя домена, потому что пользователи из разных поддоменов.)
Я нашел контейнер разделов в CN = Разделы, CN = Конфигурация, которая содержит все домены.
Когда вы сопоставляете пользователя с partion, вы можете прочитать настоящее доменное имя из свойства nETBIOSName + "\" + sAMAccountName.
Это предполагает, что results
- это SearchResultCollection, полученная из DirectorySearcher, но вы должны иметь возможность получить ObjectID непосредственно из DirectoryEntry.
SearchResult result = results[0];
var propertyValues = result.Properties["objectsid"];
var objectsid = (byte[])propertyValues[0];
var sid = new SecurityIdentifier(objectsid, 0);
var account = sid.Translate(typeof(NTAccount));
account.ToString(); // This give the DOMAIN\User format for the account
К сожалению, вы не найдете то, что ищете в DirectoryEntry.
У вас есть sAMAccountName
, который обычно похож на myuser
(без домена). У вас есть distinguishedName
, что-то вроде LDAP://cn=joe myuser,cn=Users,dc=yourCompany,dc=com
. У вас также есть userPrincipalName
, но обычно это имя в формате [email protected]
.
Но вы, к сожалению, не найдете в нем атрибута domain\MyUser
. Вам нужно будет собрать это вместе со своей информацией о доменном имени и имени sAMAccountName в DirectoryEntry.
Для получения дополнительной информации и некоторых отличных листов Excel по всем свойствам LDAP и WinNT в System.DirectoryServices посетите веб-сайт Hilltop Lab от ADSI MVP Ричард Мюллер.
Марк
Чтобы получить доменное имя DirectoryEntry, вы можете использовать рекурсию
directoryEntry.Parent
.
И тогда, если directoryEntry.SchemaClassName == "domainDNS"
вы можете получить доменное имя следующим образом:
directoryEntry.Properties["Name"].Value
public static string GetDomainNameUserNameFromUPN(string strUPN)
{
try
{
WindowsIdentity wi = new WindowsIdentity(strUPN);
WindowsPrincipal wp = new WindowsPrincipal(wi);
return wp.Identity.Name;
}
catch (Exception ex)
{
}
return "";
}
Если вы используете библиотеки System.DirectoryServices, у вас должен быть SearchResultsCollection от DirectorySearcher.
Внутри каждой коллекции свойств SearchResult существует свойство "различающееся имя". Это будет содержать все части DC, которые составляют домен, к которому принадлежит ваш каталог.
Я продлеваю предыдущий ответ @laktak, чтобы предоставить детали того, что он имел в виду.
В CN=Partitions,CN=Configuration
есть контейнер разделов, содержащий все домены, которые предоставляют вам cn
, являющееся доменным именем Netbios, и свойство nCName
, которое содержит префикс distinguishedName
, который пользователь будет иметь, если он находится в этот домен.
Итак, начните с поиска ldap для (objectClass=*)
в CN=Partitions,CN=Configuration
и сохраните пары (cn
, nCName
) каждого результата на карте.
Затем вы запрашиваете ldap с помощью (sAMAccountName=USERIDHERE)
и получаете distinguishedName
от пользователя. Теперь пройдите пары (cn
, nCName
) и найдите nCName
, который префикс distinguishedName
от пользователя, а соответствующий cn
- это ваше желаемое имя домена.
1) Вы можете получить userPrincipalName из DirectoryEntry.
2) Затем разделите UPN между именем пользователя и доменным именем.
3) Затем вызовите GetNetBIOSName() на нем.
public static DirectoryEntry GetDirectoryObject(string strPath)
{
if (strPath == "")
{
strPath = ConfigurationManager.AppSettings["LDAPPath"]; //YOUR DEFAULT LDAP PATH ie. LDAP://YourDomainServer
}
string username = ConfigurationManager.AppSettings["LDAPAccount"];
string password = ConfigurationManager.AppSettings["LDAPPassword"];
//You can encrypt and decrypt your password settings in web.config, but for the sake of simplicity, I've excluded the encryption code from this listing.
}
catch (Exception ex)
{
HttpContext.Current.Response.Write("user: " + username + ", LDAPAccount: "+ ConfigurationManager.AppSettings["LDAPAccount"] + ".<br /> "+ ex.Message +"<br />");
if (HttpContext.Current.User.Identity != null)
{
HttpContext.Current.Response.Write("HttpContext.Current.User.Identity: " + HttpContext.Current.User.Identity.Name + ", " + HttpContext.Current.User.Identity.IsAuthenticated.ToString() + "<br />");
HttpContext.Current.Response.Write("Windows Identity: " + WindowsIdentity.GetCurrent().Name + ", " + HttpContext.Current.User.Identity.IsAuthenticated.ToString());
}
else
{
HttpContext.Current.Response.Write("User.Identity is null.");
}
HttpContext.Current.Response.End();
}
DirectoryEntry oDE = new DirectoryEntry(strPath, username, password, AuthenticationTypes.Secure);
return oDE;
}
public static string GetNetBIOSName(string DomainName)
{
string netBIOSName = "";
DirectoryEntry rootDSE =GetDirectoryObject(
"LDAP://"+DomainName+"/rootDSE");
string domain = (string)rootDSE.Properties[
"defaultNamingContext"][0];
// netBIOSName += "Naming Context: " + domain + "<br />";
if (!String.IsNullOrEmpty(domain))
{
//This code assumes you have a directory entry at the /CN=Partitions, CN=Configuration
//It will not work if you do not have this entry.
DirectoryEntry parts = GetDirectoryObject(
"LDAP://"+DomainName+"/CN=Partitions, CN=Configuration," + domain);
foreach (DirectoryEntry part in parts.Children)
{
if ((string)part.Properties[
"nCName"][0] == domain)
{
netBIOSName += (string)part.Properties[
"NetBIOSName"][0];
break;
}
}
}
return netBIOSName;
}
public static string GetDomainUsernameFromUPN(string strUPN)
{
string DomainName;
string UserName;
if (strUPN.Contains("@"))
{
string[] ud = strUPN.Split('@');
strUPN= ud[0];
DomainName = ud[1];
DomainName=LDAPToolKit.GetNetBIOSName(DomainName);
UserName= DomainName + "\\" + strUPN;
}
else
{
UserName= strUPN;
}
return UserName;
}