Помогите считать из Active Directory

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Помогите считать из Active Directory

Сообщение WadimZapara »

Уважаемые знатоки!
Задача: в сети под управлением Windows 2k с Active Directory пользователи в зависимости от расположения их аккаунта в Organization Units должны получать разные возможности в одном и том же приложении, так что: достаточно переместить пользователя в другое подразделение в Active Directory и приложение предоставит ему уже другой функциональный набор.
Текущего User'а, его права, вхождение в группы безопасности, IP-адрес, MachinName - я определить умею.
А вот до Active Directory как добраться - ума не приложу. Помогите!
Средство разработки C55ee
Компьютер имеет то преимущество перед мозгом, что им пользуются...
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Помогите считать из Active Directory

Сообщение WadimZapara »

Спасибо за интерес. Решение найдено:
В окне вызвать функцию типа FromAD, например так: Message(FromAD())

Код: Выделить всё

  MAP
       FromAD(),String
  END
Window Window,AT(0,0,0,0).
  CODE
    Open(Window)
    Message(FromAD())
    Close(Window)
  RETURN

FromAD   FUNCTION() !,String
mOcx   Signed(0)
tcs    CString(1024)
  CODE
  mOcx = Create(0, CREATE:ole)
  mOcx{PROP:Create} = 'ADSystemInfo'
  If mOcx{PROP:Object} Then
    tcs = mOcx{'UserName'}
    mOcx{PROP:Release} = 1
    mOcx{PROP:deactivate} = 1
  End
  Destroy(mOcx)
  Return(tcs)
Компьютер имеет то преимущество перед мозгом, что им пользуются...
ru_alex
Ветеран
Сообщения: 333
Зарегистрирован: 21 Сентябрь 2005, 11:05
Откуда: Нижний Новгород
Контактная информация:

Re: Помогите считать из Active Directory

Сообщение ru_alex »

Текущего User'а, его права, вхождение в группы безопасности, IP-адрес, MachinName - я определить умею.
А если не трудно, можно кусок кода или пример работы с Active Directory, плиз?
Что-то подобное в ближайшее время придется делать...
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Помогите считать из Active Directory

Сообщение WadimZapara »

Текущего User'а, его права, вхождение в группы безопасности, IP-адрес, MachinName - я определить умею.
Это уже не Active Directory - это функции NET API
Сделай тему. Отвечу.
Компьютер имеет то преимущество перед мозгом, что им пользуются...
ru_alex
Ветеран
Сообщения: 333
Зарегистрирован: 21 Сентябрь 2005, 11:05
Откуда: Нижний Новгород
Контактная информация:

Re: Помогите считать из Active Directory

Сообщение ru_alex »

Я наверное неудачно цитату привел. Просто из этой строчки я понял, что уже есть наработки.
Мне нужна поддержка авторизации в программе именно через Active Directory. Некоторые клиенты требуют.
Я сообственно пока с этим делом не работал, и смутно понимаю как там все устроено, но задача такая стоит, в ближайшее время придется разбираться. Может напишешь несколько строк о том, как прога на кларион должна связываться с Active Directory, читать данные и т.д., заранее спасибо.
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Помогите считать из Active Directory

Сообщение WadimZapara »

Выше приведён полностью работоспособный кусок кода для выяснения зарегистрированного в Active Directory выводимого имени пользователя, который запустил данное приложение.
Функция вернёт в данном случае нечто вроде LDAP-строки (двойные кавычки - мои):
"CN=Вадим М.Запара,OU=Привелигированные,OU=Отдел Какой-то,OU=Управление Большое,DC=xxx,DC=yyy,DC=tambov,DC=ru"
(Если полагать, что доменное имя: xxx.yyy.tambov.ru, а мой аккаунт обзывается в Active Directory как "Вадим М.Запара" и расположен в Organization Unit с названием "Привелигированные", которая вложена в OU с названием "Отдел Какой-то", который находится в OU "Управление Большое", которое - в корне AD)

Аналогично, для получения имени компа, зарегистрированного в Active Directory, нужно вместо строки

Код: Выделить всё

  tcs = mOcx{'UserName'}
использовать

Код: Выделить всё

  tcs = mOcx{'ComputerName'}
Результатом будет LDAP-строка вида: "CN=VASHA-MASHINE,CN=Computers,DC=xxx,DC=yyy,DC=tambov,DC=ru"

Если в названиях Organization Unit присутствует "," или "=", или "\" - они в возвращаемой строке будут выглядеть как "\," , "\=", "\\".

Для получения доменного имени используйте имя свойства 'DomainDNSName'. Получите: xxx.yyy.tambov.ru
Для получения пред-Win2000 имени домена используйте имя свойства ''DomainShortName'.

У меня указанное работает на тачках с Win-2000 (srv, pro), Win-2003, Win-Xp
На Win-NT4 и Win-98 не работает (ошибки нет - но результат пустой)
Компьютер имеет то преимущество перед мозгом, что им пользуются...
ru_alex
Ветеран
Сообщения: 333
Зарегистрирован: 21 Сентябрь 2005, 11:05
Откуда: Нижний Новгород
Контактная информация:

Re: Помогите считать из Active Directory

Сообщение ru_alex »

Спасибо!
Все подробно и понятно. Буду пробовать.
Аватара пользователя
WadimZapara
Активист
Сообщения: 181
Зарегистрирован: 11 Июнь 2008, 12:11
Откуда: Тамбов

Re: Помогите считать из Active Directory

Сообщение WadimZapara »

НАЙДЕНО НЕПЛОХОЕ РЕШЕНИЕ:

Код: Выделить всё

!===============================================================================================================================
   LDAP_User(String UserName, String DomainNameWithPoints, |
             Byte TmpWindow=TRUE, Signed NumFieldOCX=0, <Window W>, Byte DestroyField=TRUE),String,Name('LDAP_User@ZWM_Function')
!
! НАЗНАЧЕНИЕ:  СЧИТАТЬ (ИСПОЛЬЗУЯ МЕХАНИЗМ OLE) РАСПОЛОЖЕНИЕ АККАУНТА ПОЛЬЗОВАТЕЛЯ В ACTIVE DIRECTORY
!              ПО ИМЕНИ ПОЛЬЗОВАТЕЛЯ И ИМЕНИ ДОМЕНА (С ТОЧКАМИ)
! Параметры:
!  1) UserName             - Имя входа пользователя (аккаунт, Login_Name)
!  2) DomainNameWithPoints - имя домена с точками
!  3) TmpWindow            - Должна ли функция создать временное окно для вычислений
!  4) NumFieldOCX          - Использовать экранный объект с этим номером, при необходимости - создать
!  5) W                    - Метка окна, которое использовать, если не создавать временное (при TmpWindow=FALSE),
!                            если не указано, то используется текущее (при TmpWindow=FALSE)
!  6) DestroyField         - Разрушить экранный OLE-объект по завершении операции
!
! Возвращает LDAP-строку расположения аккаунта пользователя в Active Directory.
!
! ДЛЯ ИНФОРМАЦИИ: 1) использует подключение к Active Directory через механизм ADODB.Connection - OLE
!                 2) работает на Win2k, Win2k3, WinXp
!                    и при установленном клиенте Active Directory - на WinNT4 и Win9x
!
! ПРИМЕР:
! Получение данных о компьютере, на котором исполняется вызвавшая программа, и текущем пользователе из Active Directory:
!  PROGRAM
!tcs          CString(1024)
!UserName     CString(256)
!CompDNSName  CString(256)
!NumAdapters  Byte
!x            Signed,Auto
!  MAP
!    MODULE('OCXWork.dll')
!      INCLUDE('OCXWork.inc')
!    END
!  END
!  CODE
! UserName = GetLoginName()                                   ! предполагается, что выдаёт аккаунт пользователя, запустившего программу
! GetNetInfo(CompDNSName)                                     ! предполагается, что выдаёт DNS-имя компа, где запущена прога: compname.xxx.yyy.zzz
! Выделяем имя домена (отрезанием собственно имени компа)
! x = InString('.', CompDNSName)
! If x Then CompDNSName = CompDNSName[x+1 : Len(CompDNSName)].
! Получаем строку вида "CN=Вадим М.Запара,OU=Привилегированные,OU=Отдел какой-то,OU=Управление какое-то, DC=xxx,DC=yyy,DC=zzz"
! tcs = LDAP_User(UserName, CompDNSName)
! Message(UserName &'|'& CompDNSName &'||'& tcs, 'Для пользователя')
!  RETURN

LDAP_User FUNCTION (String UserName, String DomainNameWithPoints, Byte TmpWindow=TRUE, Signed NumFieldOCX=0, <Window W>, Byte DestroyField=TRUE) !,String
TmpWin        Window,AT(0,0,0,0).
CurrWin       &Window
objConnection Signed(0)

objRecordset  CString(21)
ret           CString(1024)
  CODE
  CurrWin &= SYSTEM{PROP:Target}
  IF TmpWindow THEN                          ! требуется создать временное окно
    Open(TmpWin)
  ELSIF ~Omitted(5) And ~(CurrWin &= W) THEN ! окно указано и оно не текущее - переключаемся в него
    SetTarget(W)
  END !IF
  objConnection = Create(NumFieldOCX, CREATE:ole)
  IF ~objConnection And NumFieldOCX{PROP:Type} = CREATE:ole THEN  ! Ошибка создания экранного объекта, т.е., с таким номером уже есть
    objConnection = NumFieldOCX
  END !IF

  IF objConnection THEN
    objConnection{PROP:Create} = 'ADODB.Connection'
    If objConnection{PROP:Object} Then 
      objConnection{'Provider'} = 'ADsDSOObject'
      objConnection{'Properties("Encrypt Password").Value'} = False
      objConnection{'Properties("ADSI Flag").Value'} = -2147483648
      objConnection{'Properties("Integrated Security").Value'} = 'SSPI'
      objConnection{'Properties("Mode").Value'} = 'Read'
      objConnection{'Properties("Bind Flags").Value'} = 0
      objConnection{'Open'}
      ! Готовим строку подключения
      ret = 'Execute("SELECT ADsPath FROM ''LDAP://' & DomainNameWithPoints &''' WHERE objectCategory=''user'' And samAccountName='''& UserName &'''")'
      objRecordset = objConnection{ret}
      Clear(ret)
      if objConnection{objRecordset &'.EOF()'} <> '-1' then
        ret = objConnection{objRecordset &'.Fields.Item("ADsPath").Value'}
        If ret[1 : Len(DomainNameWithPoints)+Size('LDAP:///')] = 'LDAP://' & DomainNameWithPoints &'/' Then
          ret = ret[Len(DomainNameWithPoints)+Size('LDAP:///')+1 : Len(ret)]
        End
      end !if objConnection{...
    Else
      ret = 'Error: ADODB.Connection Not Worked'
    End !If objConnection{PROP:Object}
    If DestroyField Or TmpWindow Then Destroy(objConnection).
  ELSE
    ret = 'Error: Display object not created'
  END !IF objConnection
  IF TmpWindow THEN Close(TmpWin).
  IF ~(CurrWin &= NULL) THEN SetTarget(CurrWin).
 Return(ret)
Компьютер имеет то преимущество перед мозгом, что им пользуются...
ru_alex
Ветеран
Сообщения: 333
Зарегистрирован: 21 Сентябрь 2005, 11:05
Откуда: Нижний Новгород
Контактная информация:

Re: Помогите считать из Active Directory

Сообщение ru_alex »

Спасибо!
kreator
✯ Ветеран ✯
Сообщения: 4960
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 6 раз
Поблагодарили: 19 раз

Помогите считать из Active Directory

Сообщение kreator »

А можно вытащить из AD пароль пользователя? Возник такой вопрос: пользователей идентифицировать как пользователей домена, но заставить их вводить ещё раз пароль, мол есть компы, где могут работать кто угодно (на этих компах вход в домен, грубо говоря, через гостевую запись).
We are hard at work… for you. :)
kreator
✯ Ветеран ✯
Сообщения: 4960
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 6 раз
Поблагодарили: 19 раз

Помогите считать из Active Directory

Сообщение kreator »

Всё же нужна проверка доменной аутентификации при входе в программу. Нашёл вот такую функцию:

Код: Выделить всё

HRESULT ADsOpenObject(
  _In_  LPCWSTR lpszPathName,
  _In_  LPCWSTR lpszUserName,
  _In_  LPCWSTR lpszPassword,
  _In_  DWORD   dwReserved,
  _In_  REFIID  riid,
  _Out_ VOID    **ppObject
);
(https://msdn.microsoft.com/en-us/librar ... s.85).aspx).
С декларацией справился. Но... В msdn написано, что тип LPCWSTR указатель на юникод строку. А в описании самой функции слова "pointer" нет, как будто передавать надо не адрес, а строку. Я что должен подсунуть? Всё таки адрес? И с двумя последними параметрами вопрос. Что это? Формальные параметры или я их должен откуда-то получить?
We are hard at work… for you. :)
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3131
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 10 раз
Поблагодарили: 28 раз
Контактная информация:

Помогите считать из Active Directory

Сообщение Дед Пахом »

LPCWSTR это указатель, а слово pointer опускают для краткости.
Предпоследний (?) это guid интерфейса искомого объекта,
IID_IADs is defined as FD8256D0-FD15-11CE-ABC4-02608C9E7553
Последний параметр ppObject это вообще возвращаемон значение.
В dwReserved я так понял надо передавать один или несколько флагов из ADS_AUTHENTICATION_ENUM:

Код: Выделить всё

typedef enum  { 
  ADS_SECURE_AUTHENTICATION  = 0x1,
  ADS_USE_ENCRYPTION         = 0x2,
  ADS_USE_SSL                = 0x2,
  ADS_READONLY_SERVER        = 0x4,
  ADS_PROMPT_CREDENTIALS     = 0x8,
  ADS_NO_AUTHENTICATION      = 0x10,
  ADS_FAST_BIND              = 0x20,
  ADS_USE_SIGNING            = 0x40,
  ADS_USE_SEALING            = 0x80,
  ADS_USE_DELEGATION         = 0x100,
  ADS_SERVER_BIND            = 0x200,
  ADS_NO_REFERRAL_CHASING    = 0x400,
  ADS_AUTH_RESERVED          = 0x80000000
} ADS_AUTHENTICATION_ENUM;
С уважением, ДП
kreator
✯ Ветеран ✯
Сообщения: 4960
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 6 раз
Поблагодарили: 19 раз

Помогите считать из Active Directory

Сообщение kreator »

Дед Пахом писал(а): 15 Ноябрь 2017, 12:37 Предпоследний (?) это guid интерфейса искомого объекта,

IID_IADs is defined as FD8256D0-FD15-11CE-ABC4-02608C9E7553
В файле svcomdef.inc этот REFIID описан как Long, хотя в MSDN это guid. Вот это меня смутило. Там же есть тип GUID. Чему верить? На декларацию с Long'ом компилятор не заругался (на GUID, впрочем, тоже). ДП, подскажи, пожалуйста, как константу IID_IADs описать, если это возможно? Я её попробую подсунуть в функцию.
We are hard at work… for you. :)
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3131
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 10 раз
Поблагодарили: 28 раз
Контактная информация:

Помогите считать из Active Directory

Сообщение Дед Пахом »

Как-то так:

Код: Выделить всё

IID_IADs          GROUP
data1                             LONG(0FD8256D0H)
data2                             SHORT(0FD15H)
data3                             SHORT(11CEH)
data4                             STRING('<0ABH><0C4H><2H><60H><8CH><9EH><75H><53H>')
                              END
ref_IID_IADs  REFIID, AUTO
  CODE
  ref_IID_IADs  = ADDRESS(IID_IADs)
С уважением, ДП
kreator
✯ Ветеран ✯
Сообщения: 4960
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 6 раз
Поблагодарили: 19 раз

Помогите считать из Active Directory

Сообщение kreator »

Спасибо! Буду пробовать. Ещё, если можно, вопрос (в качестве образования). Пример с MSDN для С++:

Код: Выделить всё

hr = ADsOpenObject(L"LDAP://CN=Jeff,DC=Fabrikam,DC=com",
                   "jeffsmith",
                   "etercespot",
                   ADS_SECURE_AUTHENTICATION, 
                   IID_IADs,
                   (void**) &pObject);
"L" впереди строковой константы означает Unicode (уже выяснил). Не пойму почему у двух следующих констант "L" нет? Спецсимволов нет?
We are hard at work… for you. :)
Ответить