Предлагаю вам рассмотреть возможность получения информации из Active Directory на стороне сервера.
&НаСервере
Функция ПолучитьИнформациюActiveDirectoryНаСервере(пИмяДомена, пПользователь, пПароль, пУсловияОтбора)
Перем Пользователь,Пароль,Домен,Стр,Контроллер,Отбор,Подразделение,Группа;
//ADsPath,Name,Mail,telephoneNumber,displayName,sAMAccountName,department
СтрКолонок = Новый Структура("ADsPath,sn,givenName,Name,Mail,telephoneNumber,displayName,sAMAccountName,department,userPrincipalName");
ТаблицаРезультат = Новый ТаблицаЗначений;
Для Каждого СтрКол Из СтрКолонок Цикл
ТаблицаРезультат.Колонки.Добавить(СтрКол.Ключ, Новый ОписаниеТипов("Строка"));
КонецЦикла;
ТаблицаРезультат.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка"));
ТаблицаРезультат.Колонки.Добавить("АутентификацияОС", Новый ОписаниеТипов("Строка"));
ТаблицаРезультат.Колонки.Добавить("Фамилия", Новый ОписаниеТипов("Строка"));
ТаблицаРезультат.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
ТаблицаРезультат.Колонки.Добавить("Отчество", Новый ОписаниеТипов("Строка"));
ТаблицаРезультат.Колонки.Добавить("Служебный", Новый ОписаниеТипов("Булево"));
ТаблицаРезультат.Колонки.Добавить("ДоменWINS", Новый ОписаниеТипов("Строка"));
ТаблицаРезультат.Колонки.Добавить("ДоменDNS", Новый ОписаниеТипов("Строка"));
AD_Domain_DC = пИмяДомена; //Имя домена - Перед (Windows 2000), Имя WINS
//Домен="...................."; //Каноническое имя домена, Имя DNS
Пользователь = пПользователь;
Пароль = пПароль;
АДСИ = Новый COMОбъект("ADSystemInfo");
Домен = АДСИ.DomainDNSName; //Каноническое имя домена, Имя DNS
//Но на самом деле хватит и обычного пользователя домена
//Пользователь="администратор@" + Домен;
//Пароль="СуперпарольАдминистратора";
ДСО = ПолучитьCOMОбъект("GC:");
Корень = ДСО.OpenDSObject("GC://RootDSE", ""+Пользователь+"@"+Домен, Пароль,1);
НашДомен = Корень.Get("defaultNamingContext");
ЗаписьАДО = Новый COMОбъект("ADODB.recordset");
СоединениеАДО = Новый COMОбъект("ADODB.Connection");
СоединениеАДО.Provider = "ADsDSOObject";
ADS_SECURE_AUTHENTICATION = 1; // Позволяет читать данные, когда не разрешен анонимный доступ
СоединениеАДО.Properties("User ID" ).Value = AD_Domain_DC+"\"+Пользователь;
СоединениеАДО.Properties("Password" ).Value = Пароль;
СоединениеАДО.Properties("ADSI Flag").Value = ADS_SECURE_AUTHENTICATION;
СоединениеАДО.Open("ADs Provider");
Если пУсловияОтбора = 1 Тогда
//Все пользователи, кроме отключенных
ТектсУсловияОтбора = "(!useraccountcontrol:1.2.840.113556.1.4.803:=2)";
ИначеЕсли пУсловияОтбора = 2 Тогда
//Только отключенные пользователи
ТектсУсловияОтбора = "(useraccountcontrol:1.2.840.113556.1.4.803:=2)";
Иначе
//Все пользователи...
ТектсУсловияОтбора = "";
КонецЕсли;
ПоляЗапроса = "ADsPath,sn,givenName,Name,Mail,telephoneNumber,displayName,sAMAccountName,department,userPrincipalName";
ЗаписьАДО.Open("<GC://" + СокрЛП(НашДомен) + ">;(&(objectCategory=person)(objectClass=user)"+ТектсУсловияОтбора+"); "+ПоляЗапроса+" ;subtree", СоединениеАДО, 0, 1);
//ADsPath,Name,Mail,telephoneNumber,displayName,sAMAccountName,department
//Сообщить("ИмяПользователя " + СокрЛП(ВыборкаАДО.Fields("displayName").Value));
//Сообщить("ИмяАккаунта " + СокрЛП(ВыборкаАДО.Fields("sAMAccountName").Value));
//Сообщить("Подразделение " + СокрЛП(ВыборкаАДО.Fields("department").Value));
//Сообщить("Почта " + СокрЛП(ВыборкаАДО.Fields("mail").Value));
//Сообщить("Телефон " + СокрЛП(ВыборкаАДО.Fields("telephoneNumber").Value));
Если ЗаписьАДО.RecordCount > 0 Тогда
Пока Не ЗаписьАДО.EOF Цикл
Для Каждого СтрКол Из СтрКолонок Цикл
СтрКолонок[СтрКол.Ключ] = ЗаписьАДО.Fields(СтрКол.Ключ).Value;
КонецЦикла;
НоваяСтрока = ТаблицаРезультат.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока,СтрКолонок);
Если НЕ ПустаяСтрока(НоваяСтрока.userPrincipalName) Тогда
НоваяСтрока.АутентификацияОС = "\\"+AD_Domain_DC+"\"+НоваяСтрока.sAMAccountName;
КонецЕсли;
//Наименование
НоваяСтрока.Наименование = СокрЛП(НоваяСтрока.displayName);
Если ПустаяСтрока(НоваяСтрока.Наименование) Тогда
НоваяСтрока.Наименование = СокрЛП(НоваяСтрока.Name);
КонецЕсли;
//Отчество
НоваяСтрока.Фамилия = СокрЛП(НоваяСтрока.sn);
НоваяСтрока.Имя = СокрЛП(НоваяСтрока.givenName);
НовоеИмя = "";
НоваяСтрока.Отчество = ПолучитьОтчествоИзАД(НоваяСтрока.sn, НоваяСтрока.givenName, НоваяСтрока.Name, НовоеИмя);
Если НЕ ПустаяСтрока(НовоеИмя) Тогда
НоваяСтрока.Имя = НовоеИмя;
КонецЕсли;
НоваяСтрока.Служебный = ПустаяСтрока(НоваяСтрока.userPrincipalName);
НоваяСтрока.ДоменWINS = AD_Domain_DC;
НоваяСтрока.ДоменDNS = Домен;
Попытка
ЗаписьАДО.MoveNext();
Исключение
Прервать;
КонецПопытки;
КонецЦикла;
КонецЕсли;
ЗаписьАДО.Close();
ЗаписьАДО = Неопределено;
СоединениеАДО.Close();
СоединениеАДО = Неопределено;
Возврат ТаблицаРезультат;
КонецФункции
&НаСервере
Функция УдалитьДвойныеПробелыИзСтроки(ФИО)
РезФун = СокрЛП(ФИО);
РезФун = СтрЗаменить(РезФун, " ", " ");
Пока Найти(РезФун, " ") > 0 Цикл
РезФун = СтрЗаменить(РезФун, " ", " ");
КонецЦикла;
Возврат РезФун;
КонецФункции
&НаСервере
Функция ПолучитьОтчествоИзАД(Знач Фамилия, Знач Имя, Знач ФИО, НовоеИмя)
Если ПустаяСтрока(Фамилия) или ПустаяСтрока(Имя) или ПустаяСтрока(ФИО) Тогда
Возврат "";
КонецЕсли;
Фамилия = СокрЛП(Фамилия);
Имя = СокрЛП(Имя);
ФИО = СокрЛП(ФИО);
//Избавимся от лишних пробелов ФИО
ФИО = УдалитьДвойныеПробелыИзСтроки(ФИО);
Имя = УдалитьДвойныеПробелыИзСтроки(Имя);
МассивСтрок = СтрРазделить(ФИО," ",Истина);
Если МассивСтрок.Количество() <> 3 Тогда Возврат ""; КонецЕсли;
МассивСтрокИмя = СтрРазделить(Имя," ",Истина);
//Убрать Фамилию
Если Найти(ФИО+" ", Фамилия+" ") = 0 Тогда Возврат ""; КонецЕсли;
ФИО = СокрЛП(СтрЗаменить(ФИО+" ", Фамилия+" ", ""));
//Убрать Имя
Если МассивСтрокИмя.Количество() = 2 Тогда
НовоеИмя = СокрЛП(МассивСтрокИмя[0]);
НовоеОтчество = СокрЛП(МассивСтрокИмя[1]);
//Убрать Имя
Если Найти(ФИО+" ", НовоеИмя+" ") = 0 Тогда
НовоеИмя = "";
Возврат "";
КонецЕсли;
ФИО = СокрЛП(СтрЗаменить(ФИО+" ", Фамилия+" ", ""));
//Найти Отчество
Если Найти(ФИО+" ", НовоеОтчество+" ") = 0 Тогда
НовоеИмя = "";
Возврат "";
КонецЕсли;
ФИО = НовоеОтчество;
Иначе
Если Найти(ФИО+" ", Имя+" ") = 0 Тогда Возврат ""; КонецЕсли;
ФИО = СокрЛП(СтрЗаменить(ФИО+" ", Имя+" ", ""));
КонецЕсли;
Возврат ФИО;
КонецФункции
Примеры запросов Active Directory
- Поиск административных учётных записей по атрибуту adminCount. Если пользователь является членом защищенной группы (например, Domain Admins, Enterprise Admins и т.п.), ему назначаются ACL, установленные в объекте AdminSDHolder в AD, а атрибуту adminCount пользователя присваивается значение 1.
(objectClass=user)(objectCategory=Person)(adminCount=1)
При удалении пользователя из привилегированной группы процесс AdminSDHolder не возвращает атрибут adminCount к прежнему значению, т.е. в результаты запроса попадут и те учётные записи, которые, когда-либо входили в одну из защищённых групп.
- Все объекты, защищённые AdminSDHolder:
(adminCount=1)
- Поиск всех отключенных учётных записей компьютеров:
(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=2))
- Все пользователи:
(&(objectCategory=user)(objectClass=user)(userPrincipalName=*))
Или более эффективный вариант:
(sAMAccountType=805306368)
- Все пользователи, кроме отключенных:
(objectCategory=person)(objectClass=user)(!useraccountcontrol:1.2.840.113556.1.4.803:=2)
- Пользователи, которые должны сменить пароль:
(objectCategory=person)(objectClass=user)(pwdLastSet=0)(!useraccountcontrol:1.2.840.113556.1.4.803:=2)
- Пользователи, которые будут заблокированы после ещё одной неудачной попытки ввода пароля. В запросе используется атрибут badPwdCount. Значение нужно указать в соответствии с вашими парольными политиками в домене и учётом гранулированных парольных политик, если используются.
(objectCategory=user)(badPwdCount>=6)
- Пользователи с бессрочным паролем (Password never expires):
(objectcategory=user)(userAccountControl:1.2.840.113556.1.4.803:=65536)
- Все пользователи, которые не меняли свой пароль с указанной даты
(&(objectCategory=person)(objectClass=user)(pwdLastSet<=131720255990000000))
PwdLastSet для определённой даты можно получить с помощью PowerShell:
$date = '28 May 2018 23:59:59' (Get-Date $date).ToFileTimeUTC()
Подробнее о атрибуте Pwd-Last-Set см. здесь.
- Заблокированные пользователи:
(objectCategory=person)(objectClass=user)(useraccountcontrol:1.2.840.113556.1.4.803:=16)
- Пользователи, у которых не заполнено поле должность. По аналогии можно найти пользователей по другим полям, либо по маске *название должности:
(&(objectCategory=user)(objectClass=user)(!title=*))
- Пользователи, созданные за определённый период. Формат дат используется следующий:
YYYY MM DD HH mm ss.s Z 2017 01 01 00 00 00.0 Z
(objectCategory=user)(whenCreated>=20170101000000.0Z&<=20171201000000.0Z&)
objectCategory можно использовать любой, например group, computer, contact и др.
- Пользователи без фотографии (атрибут thumbnailPhoto):
(objectCategory=user)(objectClass=user)(userPrincipalName=*)(!thumbnailPhoto=*)
- Все пользователи с Email адресом:
(objectcategory=person)(mail=*)
- Все пользователи без Email адреса:
(objectcategory=person)(!mail=*)
- Все пользователи у которых переопределена квота на почтовый ящик Exchange:
(&objectCategory=user)(mDBUseDefaults=FALSE)
- Все пользователи, скрытые из адресной книги Exchange:
(objectCategory=person)(objectClass=user)(msExchHideFromAddressLists=TRUE)
- Все компьютеры:
(objectCategory=computer)
- Все компьютеры Windows 10:
(objectCategory=computer)(operatingSystem=Windows 10*)
- Все компьютеры Windows Server 2016:
(objectCategory=computer)(operatingSystem=Windows Server 2016*)
- Windows Server 2016 Standard:
(objectCategory=computer)(operatingSystem=Windows Server 2016 Standard)
- Windows Server 2016 Datacenter:
(objectCategory=computer)(operatingSystem=Windows Server 2016 Datacenter)
- Все SQL серверы, с любой ОС, у которых зарегистрирован servicePrincipalName:
(objectCategory=computer)(servicePrincipalName=MSSQLSvc*)(operatingSystem=Windows Server*)
- Все Exchange серверы:
(objectCategory=computer)(servicePrincipalName=exchangeMDB*)(operatingSystem=Windows Server*)
- Все контакты:
(objectClass=contact)
- Поиск SMTP адреса по атрибуту proxyAddress. Позволяет найти любые объекты с почтовым адресом, включая общие папки Exchange:
(&proxyAddresses=smtp:*@domain.com)
- Все группы:
(objectCategory=group)
- Пустые группы, не содержащие ни одного члена:
(objectCategory=group)(!member=*)
- Все организационные подразделения:
(objectCategory=organizationalUnit)
- Все контейнеры:
(objectCategory=container)
- Все цветные принтеры на сервере печати:
(uncName=*Servername*)(objectCategory=printQueue)(printColor=TRUE)
Servername — имя сервера печати, на котором установлен и опубликован в Active Directory принтер.
- Все доверительные отношения:
(objectClass=trustedDomain)
Пример получения E_MAIL на стороне Клиента.
В качестве входного параметра должна быть указана строка вида \\Домен\Пользователь_домена
&НаКлиенте
Функция ПолучитьАдресИзADO(Знач ПользовательОС) Экспорт
Email = "";
Если ПустаяСтрока(ПользовательОС) Тогда Возврат Email; КонецЕсли;
Попытка
RootDSE = ПолучитьCOMОбъект("LDAP://RootDSE");
НашДомен = RootDSE.Get("rootDomainNamingContext");
ЗаписьАДО = Новый COMОбъект("ADODB.recordset");
СоединениеАДО = Новый COMОбъект("ADODB.Connection");
СоединениеАДО.Provider = "ADsDSOObject";
СоединениеАДО.Open("ADs Provider");
СтрокаПользователя = СокрЛП(ПользовательОС);
КоличествоСимволов = СтрЧислоВхождений(СтрокаПользователя,"\");
Пока КоличествоСимволов > 0 Цикл
Позиция = Найти(СтрокаПользователя,"\");
СтрокаПользователя = Сред(СтрокаПользователя, Позиция + 1);
КоличествоСимволов = СтрЧислоВхождений(СтрокаПользователя,"\");
КонецЦикла;
ЗаписьАДО.Open("<LDAP://" + СокрЛП(НашДомен) + ">;(&(objectCategory=person)(objectClass=user)(sAMAccountName=" + СтрокаПользователя + "));ADsPath, Mail;subtree", СоединениеАДО, 0, 1);
Если ЗаписьАДО.RecordCount > 0 Тогда
Пока Не ЗаписьАДО.EOF Цикл
Email = ЗаписьАДО.Fields("Mail").Value;
Попытка
ЗаписьАДО.MoveNext();
Исключение
Прервать;
КонецПопытки;
КонецЦикла;
КонецЕсли;
ЗаписьАДО.Close();
ЗаписьАДО = Неопределено;
СоединениеАДО.Close();
СоединениеАДО = Неопределено;
Возврат СокрЛП(Email);
Исключение
Сообщить(ОписаниеОшибки());
Возврат Email;
КонецПопытки;
КонецФункции // ПолучитьАдресИзADO()
Основные атрибуты Active Directory
Таблица основных пользовательских атрибутов Active Directory
Attribute \ Атрибут | Англоязычное название | Русскоязычное название | Value \ Значение |
OU (Organizational Unit) \ Подразделение | |||
distinguishedName | Distinguished Name | Отличительное (уникальное) имя | OU=Компания,DC=domain,DC=com |
name | Компания | ||
Group \ Группа | |||
distinguishedName | Distinguished Name | Отличительное (уникальное) имя | CN=Группа,OU=Компания,DC=domain,DC=com |
name | Группа | ||
member | Members | Члены группы (какие пользователи входят в данную группу) | CN=Сергей Петрович Иванов,OU=Компания,DC=domain,DC=com |
User \ Пользователь | |||
DN | Distinguished Name | Отличительное (уникальное) имя | CN=Сергей Петрович Иванов,OU=Компания,DC=domain,DC=com |
DC | Domain Component | Компонент(класс) доменного имени. | DC=domain,DC=com |
OU | Organizational Unit | Подразделение | Компания |
CN | Common Name | Общее имя | Сергей Петрович Иванов |
givenName | First name | Имя | Сергей Петрович |
name | Full name | Полное имя | Сергей Петрович Иванов |
sn (SurName) | Last name | Фамилия | Иванов |
displayName | Display Name | Выводимое имя | Сергей Петрович Иванов |
Электронная почта | mail@domain.com | ||
sAMAccountName | User logon name (pre-Windows 2000) | Имя входа пользователя (пред-Windows 2000) | IvanovSP |
userPrincipalName | User logon name | Имя входа пользователя | IvanovSP@domain.com |
memberOf | Member Of | Член групп (в какую группу входит данный пользователь) | CN=Группа,OU=Компания,DC=domain,DC=com |
Атрибут userAccountControl
Иногда надо понять включена или отключена учетная запись в AD. Или что еще с ней вообще происходит. За это отвечает атрибут userAccountControl, который является суммой нескольких свойств атрибутов. При этом, значение 512 является значением по умолчанию при всех снятых флагах на вкладке «Учетная запись» и каждый дополнительный параметр прибавляется к нему. Например, значения атрибута userAccountControl для наиболее распространенных случаев:
512
— Включена (Enabled)
514 (512+2)
— Отключена (Disabled)
66048 (512+65536)
— Включена, срок действия пароля не ограничен (Enabled, password never expires)
66050 (512+65536+2)
— Отключена, срок действия пароля не ограничен (Disabled, password never expires)
Список основных значений атрибутов userAccountControl:
HEX | DEC | Описание |
0x00000002 | 2 | Учетная запись отключена |
0x00000010 | 16 | Учетная запись заблокирована |
0x00000020 | 32 | Пароль не требуется |
0x00000040 | 64 | Запретить смену пароля пользователем |
0x00000080 | 128 | Хранить пароль, используя обратимое шифрование |
0x00000200 | 512 | Учетная запись по умолчанию. Представляет собой типичного пользователя |
0x00010000 | 65536 | Срок действия пароля не ограничен |
0x00040000 | 262144 | Для интерактивного входа в сеть нужна смарт-карта |
0x00400000 | 4194304 | Без предварительной проверки подлинности Kerberos |
0x00800000 | 8388608 | Пароль пользователя истек |
Использовал следующий материал для написания функции:
- Пост № 19. FirePyres 43 13.03.19 09:09
- Работа с Active Directory из 1С
- Примеры запросов
- Интеграция 1С и Active Directory
- Пост № 5. 3762515 03.10.13 11:34
- Основные атрибуты Active Directory
Приложил обработку, но в основном она состоит из одной функции. Тестирование произведено на версии платформы 8.3.14.1976. Но к платформе код не имеет отношения. Версия конфигурации тоже неважна, работает на любой.