#active-directory #dns
#active-directory #dns
Вопрос:
Я запускаю ASP.NET приложение 4.0, которое использует имя пользователя (например, HttpContext.Current.Запрос.LogonUserIdentity.Name .toString()) для управления доступом к различным компонентам.
Возвращаемое имя пользователя имеет форму «abc jsmith», где «abc» — это имя домена, а «jsmith» — это имя пользователя для входа.
Часть модуля безопасности для этого приложения получает доступ к группам Active Directory, к которым принадлежит пользователь (например, «Бухгалтерия», «Оплачиваемые учетные записи», «Административный отдел»). Я могу получить имя пользователя из Active Directory, используя DirectoryEntry.Свойства (т.е. Система.DirectoryServices.PropertyCollection») «sAMAccountName».Значение.
Пока все в порядке, но я хочу иметь возможность расширять приложение на несколько доменов, что означает, что мне нужно иметь возможность находить доменное имя в Active Directory, а также имя пользователя для входа. Я могу получить значение «Domain» из PrincipalContext, но оно возвращает «abcdc» вместо «abc». Могу ли я предположить, что это свойство всегда будет возвращать «dc» (как в «Контроллере домена») в конце каждого домена (в этом случае я могу использовать подстроку свойства), или есть где-то еще, где я могу получить текущее доменное имя пользователя?
Ответ №1:
Единственное, что мне неясно, это ваш вопрос о получении доменного имени с учетом directoryentry в контроллере домена. Я предполагаю, что у вас есть сервер, который может видеть несколько доверенных доменов, и что пользователь может войти в ваше приложение с любого из них, так что вы не знаете, с каким доменом вам нужно протестировать членство в роли.
Для управления доступом к функциям через членство в ADGroup не могли бы вы использовать
HttpContext.Current.User.IsInRole("appdomaingroupname")
где пользователь.Identity.Name ==»пользовательский доменuser». Я не знаком с проблемами доверия к домену, но это предполагает, что вы можете добавлять пользователей из доверенного домена в группу доменов, которую вы контролируете, поэтому вам не нужно беспокоиться о расположении домена группы.
Если вы не можете, или если у вас одинаковое имя группы в каждом отдельном домене, то вы могли бы сделать что-то вроде этого?
HttpContext.Current.User.IsInRole(userDomainname "groupname")
Некоторые моменты:
- если у вас уже нет большой установленной базы кода AD, я бы рекомендовал использовать объекты из системы.DirectoryServices.Пространство имен AccountManagement.
- Я настоятельно рекомендую утилиту ADExplorer от Sysinternals, чтобы получить более полное представление LDAP о вашем домене (доменах), которая помогает со строками подключения LDAP и программированием каталогов в целом.
- Если вас устраивает взаимодействие и вам необходимо выполнить любой синтаксический анализ строки подключения LDAP, загляните на этот сайт.
- Система.DirectoryServices.Управление учетными записями.PrincipalContext.Контейнер и система.DirectoryServices.Вход в каталог. Свойства пути возвращают строку подключения LDAP с доменом в конце строки (т.е. DC=mycompany,DC=com)
- Не забывайте о надежной старой среде.Имя домена пользователя и среда.Имя пользователя (которое извлекает файл WindowsPrincipal из текущего выполняемого потока; см. Таблицу 1: Поток предоставляет CurrentPrincipal объект @ http://msdn.microsoft.com/en-us/library/Aa480475.aspx для получения отличной таблицы о том, какой текущий пользователь находится в asp.net время выполнения. )
** ОБНОВЛЕНИЕ 8/6/2011 14:15**
Если я правильно понимаю AD, домен пользователя является неотъемлемой частью пользовательского объекта, возвращаемого AD. Расширяя ваш пример с «Bob Newaccountant»…
Итак, учитывая следующие 2 домена с доверием между ними:
1. "abcdc.com"
CN=Users
CN="Bob NewAccountant"
2. "abc.com"
CN=Users
CN="Local User1"
OU=Applications
OU=MyApplication
CN=ReportReaders (Members: abcdcBNewAccountant, abcluser1)
Вы должны получить информацию о пользователях, задав следующий запрос:
//name parameter = domain
//container parameter = distinguished name
using(var ctx = new PrincipalContext(
ContextType.Domain,
name: "abc.com",
container: "OU=MyApplication,OU=Applications,DC=abc,DC=com",
"abcserviceaccountname",
"Password1"))
{
var officeGroup = GroupPrincipal.FindByIdentity(ctx,
IdentityType.SamAccountName,
"ReportReaders");
foreach(Principal prin in officeGroup.GetMembers(recursive: true))
{
Console.WriteLine("DistinguishedName: " prin.DistinguishedName
" UPN: " prin.UserPrincipalName);
}
//Should result in
// DistinguishedName: CN=luser1,CN=Users,DC=abc,DC=com UPN: luser1@abc.com
// DistinguishedName: CN=BNewAccountant,CN=Users,DC=abcdc,DC=com UPN: BNewAccountant@abcdc.com
}
Таким образом, вы должны иметь возможность получить домен пользователя через свойства active Directory Distinctedname или userPrincipalName. (Примечание: у меня нет удобной настройки для двух доменов, поэтому я не могу протестировать приведенный выше код в настоящее время.) Это становится ближе?
Комментарии:
1. Среда. UserDomainName очень полезно для поиска домена компьютера, на котором пользователь в данный момент вошел в систему. Однако мне нужно, чтобы мой администратор безопасности мог добавлять пользователей и управлять ими. Я могу получить «имя пользователя» из Active Directory, используя «sAMAccountName». Но как я могу получить доменное имя? Это реальный вопрос. И, кстати, DC = MyCompany — это не то, что я ищу. Это то, что выдает мне «abcdc». Что мне нужно, так это «abc». — Большое спасибо за ваш вклад. Это дало мне больше путей для рассмотрения. — Badger
2. Хммм… Возможно, это более базовая вещь, которую я тогда упускаю. Потому что я считаю, что единственные пользователи, которые будут сохранены в контроллере домена, могут быть из этого домена. Позвольте мне изменить свой ответ, чтобы показать, что я имею в виду.
3. Возможно, если я приведу сценарий пользователя Security Admin (SA): компания нанимает нового бухгалтера; Пользователь SA входит в приложение, которое выполняет поиск в Active Directory и возвращает список пользователей; Затем SA может выбрать пользователя (например, «Bob Newaccountant») и предоставить ему разрешения на соответствующие функции (например, отчеты). Мы хотим настроить приложение так, чтобы SA могла не только видеть всех пользователей в нашем объявлении, но и видеть, в каком домене они находятся. Это делает его более понятным? Еще раз спасибо за ваш вклад. Badger
4. Это выглядит намного ближе. Есть ли способ получить данные ctx, не зная пароля пользователя? Поскольку мы работаем с Active Directory (и группами в нем), я могу рассматривать это как цикл «foreach», но у меня не будет доступа к паролю каждого пользователя. Еще раз спасибо. Я думаю, мы на правильном пути!!
5. Потрясающе! Да, вам не нужен пароль пользователя. У нас возникла ситуация, когда мы не используем олицетворение, поэтому у нас есть специальная настройка учетной записи службы, которую мы используем для подключения к active directory (для этого и предназначены имя пользователя и пароль). Смотрите перегрузки конструктора для PrincipalContext для тех, которые не требуют имени пользователя и пароля: msdn.microsoft.com/en-us/library /… .
Ответ №2:
Вот способ WMI для его поиска. Я даю вам текст для PowerShell, но вы можете легко преобразовать его для VBScript или C #
PS C:> (Get-WmiObject Win32_NTDomain).DomainName
Будьте осторожны, доменная часть «домена до Windows 2000» может полностью отличаться от имени основного пользователя (user@domain), используемого для входа в Active Directory. ДОМЕН является основным именем управляющего доменом или доменным именем Netbios. ДОМЕН создается во время создания домена, по умолчанию это часть DNS-имени, но оно может быть полностью изменено во время создания домена.
Вы можете найти его с помощью атрибута nETBIOSName :
ldifde -f netbios.ldf -d "CN=Partitions,CN=Configuration,DC=your-DNS-Name" -r "(netbiosname=*)"
Отредактировано
Вот код CSharp
ManagementObjectSearcher domainInfos1 = new ManagementObjectSearcher("select * from WIN32_NTDomain");
foreach (ManagementObject domainInfo in domainInfos1.Get())
{
Console.WriteLine("Name : {0}", domainInfo.GetPropertyValue("Name"));
Console.WriteLine("Computer/domain : {0}", domainInfo.GetPropertyValue("Caption"));
Console.WriteLine("Domain name : {0}", domainInfo.GetPropertyValue("DomainName"));
Console.WriteLine("Status : {0}", domainInfo.GetPropertyValue("Status"));
}
Комментарии:
1. Попытался запустить «ldifde» в командном окне. Получено сообщение об ошибке «‘ldifde’ не распознается как внутренняя или внешняя команда, работоспособная программа или пакетный файл». — К счастью, в моей сети нет доменов до 2000 года. — Я рассмотрю возможность перевода вашей команды PowerShell на C #, чтобы упростить интеграцию с остальной частью приложения. — Спасибо за ваш вклад. Badger
2. Ldifde присутствует в контроллерах домена.
3. Ах, но мне нужно иметь возможность предоставить моему администратору безопасности доступ к этой информации, чтобы управлять доступом пользователей к различным частям приложения. — еще раз спасибо
4. Я отредактировал ответ. LDIFDE. EXE — это просто exe-файл, который вы можете скопировать с компьютера W2K или W2K3.
5. Это действительно хорошо работает при получении доменного имени для системы, в которой я нахожусь. Оно правильно отображает «Доменное имя: abc». Однако мне нужно иметь возможность просматривать Active Directory и проверять каждое имя и доменное имя. В противном случае я буду искать «какое доменное имя для пользователя ‘NewHire'»? Есть идеи?? Спасибо за всю вашу помощь. Я думаю, мы приближаемся к тому, что мне нужно!!
Ответ №3:
DC расшифровывается как domain component. Здесь приведено, казалось бы, приличное краткое изложение программирования с Active Directory. Там слишком много для того, чтобы сделать приличное копирование и вставить сюда, но я нашел следующее, которое может вам помочь:
domainname=inputbox("Enter DNS Domain Name" amp; vbcrlf amp; "(Leave blank for current domain):")
username=inputbox("Enter username:")
IF domainname = "" THEN
SET objRoot = GETOBJECT("LDAP://RootDSE")
domainname = objRoot.GET("defaultNamingContext")
END IF
IF username <> "" THEN
wscript.echo finduser(username,domainname)
END IF
FUNCTION FindUser(BYVAL UserName, BYVAL Domain)
ON ERROR RESUME NEXT
SET cn = CREATEOBJECT("ADODB.Connection")
SET cmd = CREATEOBJECT("ADODB.Command")
SET rs = CREATEOBJECT("ADODB.Recordset")
cn.open "Provider=ADsDSOObject;"
cmd.activeconnection=cn
cmd.commandtext="SELECT ADsPath FROM 'LDAP://" amp; Domain amp; _
"' WHERE sAMAccountName = '" amp; UserName amp; "'"
SET rs = cmd.EXECUTE
IF err<>0 THEN
FindUser="Error connecting to Active Directory Database:" amp; err.description
ELSE
IF NOT rs.BOF AND NOT rs.EOF THEN
rs.MoveFirst
FindUser = rs(0)
ELSE
FindUser = "Not Found"
END IF
END IF
cn.close
END FUNCTION
Комментарии:
1. На самом деле, в этом случае я обнаружил, что «dc» является частью доменного имени («центр разработки»), а не «компонент домена».
2. Кстати, за время моего исследования это второй раз, когда я вижу VB. Сетевой метод «GetObject», который не работает в C #. У кого-нибудь есть метод C #, который работает аналогичным образом?
Ответ №4:
Вы могли бы получить для пользователей «userprincipalname». Это выглядит как адрес электронной почты, но на самом деле является samaccountname @ domain.name . следует отметить, что домен Active Directory выглядит как доменное имя Интернета, а доменное имя netbios (‘abc’ из вашего примера) — нет.
Если вы возьмете UPN, я полагаю, что оно всегда будет содержать доменное имя с точкой.
Комментарии:
1. Изучил это, используя DirectoryEntry. Свойства[«Пользовательское имя»].Значение. Я все еще получаю «abcdc» в качестве доменного имени. Все еще изучаю проблему NetBIOS. Еще раз спасибо за ваш вклад.
2. Я получаю «DC = abcdc». У меня также возникли некоторые проблемы с доступом к имени пользователя. Я пробовал «[«Пользовательское имя пользователя»].Значение», «[«Пользовательское имя пользователя»].Значение» и обо всем остальном, что я мог придумать, но продолжаю выдавать «нулевые» значения. Они, конечно же, из DirectoryEntry. Свойства PropertyCollection. Я на правильном пути? — Еще раз спасибо, Badger