Аутентификация LDAP в .NET

Я хотел бы аутентифицировать имя пользователя и пароли для моего приложения в операционной системе Windows с любой службой каталогов. Например, это может быть активный каталог microsoft, Novell eDirecotry или SunOne. Я уже знаю, как сделать этот код изначально для Microsoft Active Direcotry с С#. (Я полностью отказался от использования ADSI и создал компромисс с низким уровнем)

Как я пытаюсь выполнить аутентификацию с помощью Novel eDirecotory, я установил проект Mono. Внутри монопроекта они предоставляют вам Novell.Directory.ldap.dll. Код выглядит примерно так же, как и для Microsoft Active Directory. (http://www.novell.com/coolsolutions/feature/11204.html)

Для SunOne мне сказали использовать тот же код, что и активный директив, но строка подключения ldap немного отличается. (http://forums.asp.net/t/354314.aspx) (http://technet.microsoft.com/en-us/library/cc720649.aspx)

Чтобы усложнить мой проект, большинство клиентов используют "учетную запись службы": это означает, что мне нужно связать с именем пользователя и паролем администратора, прежде чем я смогу аутентифицировать обычное имя пользователя и пароль. Мои вопросы: 2 части.

1) Из того, что я объяснил выше, это правильное направление, которое я должен пройти аутентификацию против каждого отдельного сервисного обслуживания?

2) Я чувствую, что мне вообще не нужно делать какой-либо из этого кода. Я также чувствую, что условие использования учетной записи службы не является существенным. Если все, о чем я забочусь, это аутентификация имени пользователя и пароля на компьютере с Windows, почему мне даже нужно использовать ldap? Я имею в виду, подумай об этом. Когда вы заходите на свой компьютер утром, вам не нужно предоставлять учетную запись службы только для входа. Я могу легко аутентифицировать имя пользователя и пароль в приглашении DOS с помощью функции runas, и мне будет отказано или нет, и вы можете проанализировать текстовый файл. Я уверен, что есть другие способы, которыми я могу передать имя пользователя и пароль операционной системе Windows, в которой я включен, и сообщит мне, является ли имя пользователя и пароль действительным для домена, в котором он включен. Я прав? Если да, то какие предложенные способы у вас есть?

Майкл Еванчик www.MikeEvanchik.com

Ответ 1

Все это можно сделать с помощью System.DirectoryServices.Protocols. Если вы создаете LdapConnection в каталоге, вы можете использовать учетную запись службы для связывания с ней, а затем сделать последующую привязку для аутентификации учетных данных.

Учетная запись службы обычно используется для ограничения доступа к механизму аутентификации сервера. Таким образом, ни один случайный человек на улице не может попытаться выполнить авторизацию с вашим сервером LDAP.

Кроме того, вы ожидаете, что каждый пользователь будет предоставлять свое выдающееся имя при входе в систему? В Active Directory требуется только имя sAMAccountName, но для других поставщиков, таких как eDirectory и SunONE, требуется различное имя для аутентификации.

Чтобы выполнить этот тип аутентификации, вам нужно будет использовать учетную запись службы, которая предоставляется для аутентификации на сервере, выполнить поиск пользователя с заданным именем пользователя и захватить это имя пользователя. Затем вы можете выполнить аутентификацию с использованием этого различающегося имени и пароля, который был предоставлен.

Это будет работать для всех LDAP-систем, за исключением Active Directory, которые будут довольны только именем sAMAccountName.

Ответ 2

Я не уверен, что полностью понимаю вопрос, но в некоторых ситуациях мне было легко аутентифицировать пользователя, просто выполнив поиск их учетной записи и используя свои учетные данные в качестве имени пользователя и пароля.

Успешный запрос означает, что все предоставленное было правильным, не обнаружив, что учетная запись означает, что что-то не так.

//use the users credentials for the query
DirectoryEntry root = new DirectoryEntry(
    "LDAP://dc=domain,dc=com", 
    loginUser, 
    loginPassword
    );

//query for the username provided
DirectorySearcher searcher = new DirectorySearcher(
    root, 
    "(sAMAccountName=" + loginUser + ")"
    );    

//a success means the password was right
bool success = false; 
try {
    searcher.FindOne();
    success = true;
}
catch {
    success = false;
}

Наверное, не "лучшая практика", но может обойти вашу проблему, которую вы имеете...

Ответ 3

У нас был веб-сайт, который должен был аутентифицировать имя пользователя и пароль для учетных данных домена и использовать функцию LogonUser API. Используйте его для сетевого входа (один из его аргументов - тип входа), и все, что он делает, проверяет учетные данные, он не выполняет такие действия, как загрузка профиля пользователя, который был бы runas. Только оговорка заключается в том, что учетная запись службы требует достаточного доступа к вызову LogonUser. Я предлагаю вам проверить документацию MSDN на наличие этого доступа, поскольку он зависит от ОС.