2014-12-22 2 views
0

Я работаю над Web Services, что подтверждает подлинность пользователей против Active Directory. Мое текущее решение работает, однако я пытаюсь использовать другой подход.Аутентификация Active Directory с использованием учетной записи службы

У меня есть Active Directory (производство), который сидит за брандмауэром. Я также установил Active Directory в DMZ. Между ними существует односторонняя связь. DMZ доверяет производству и производству не заботятся о DMZ.

То, что я пытаюсь выполнить, - это аутентифицировать всех через DMZ Active Directory. В настоящее время, исходя из имени пользователя, я знаю, для какого сервера AD для аутентификации.

Например, мое производство Active Directory (скажем домен domain.local) и мой DMZ Active Directory (скажем домен domain.public). Прежде чем выполнять аутентификацию на любом сервере AD, я проверяю, существует ли имя пользователя на одном из серверов. Затем я проверяю, активен ли пользователь, и только тогда я выполняю аутентификацию. (У меня проблемы с первой функцией, она не доходит до второй или третьей функции).

UPDATE: ДОБАВЛЕНО ВСЁ:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.Text; 
using System.DirectoryServices; 
using System.Security.Principal; 
using System.DirectoryServices.AccountManagement; 

namespace ActiveDirectory 
{ 
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together. 
public class Service1 : IService1 
{ 
    #region Does User Exist in AD 

    public string local = string.Empty; 
    public string ldappath = string.Empty; 
    public string userNameToUse = string.Empty; 
    public string domain = string.Empty; 

    public bool DoesUserExist(string userName) 
    { 
     string _userName = userName; 

     bool exist = true; 

     using (var domainContext = new PrincipalContext(ContextType.Domain, domain)) 
     { 
      using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse)) 
      { 
       if (foundUser == null) 
       { 
        exist = false; 
       } 
       else 
       { 
        return exist; 
       } 
      } 
     } 
     return exist; 
    } 

    #endregion 

    #region Check if User Active 
    public bool isActive (string userName) 
    { 
     string _userNameToBeSearched = userNameToUse; 
     string _username = string.Empty; 
     string _pwd = string.Empty; 

     if (local == "YES") 
     { 
      _username = "xx"; 
      _pwd = "xx"; 
      ldappath = "LDAP://xxx/DC=xx, DC=local"; 
     } 
     else 
     { 
      _username = "xx"; 
      _pwd = "xx"; 
      ldappath = "LDAP://xxx/DC=xx, DC=public"; 
     } 

     bool isActive = true; 

     try 
     { 
      DirectoryEntry entry = new DirectoryEntry(ldappath, _username, _pwd); 
      DirectorySearcher search = new DirectorySearcher(entry); 
      entry.AuthenticationType = AuthenticationTypes.Secure; 
      search.SearchRoot = entry; 
      search.Filter = "(SAMAccountName=" + _userNameToBeSearched + ")"; 

      SearchResult results = search.FindOne(); 

      if (results.ToString() != "") 
      { 
       int flags = Convert.ToInt32(results.Properties["userAccountControl"][0].ToString()); 

       //CHECK IF THE ACCOUNT IS DISABLED 
       if (flags == 66050) 
       { 
        isActive = false; 
       } 
      } 
     } 
     catch (DirectoryServicesCOMException ex) 
     { 
      ex.ToString(); 
     } 
     return isActive; 
    } 

    #endregion 

    #region Is user authenticated 
    public string isAuthenticated (string userName, string pwd) 
    { 
     string _userName, _pwd, message; 
     _userName = userName; 
     _pwd = pwd; 

     char[] splitchar = { '@' }; 

     string[] strSplit = _userName.Split(splitchar); 

     string z = strSplit[0]; 

     if (strSplit.Length == 2) 
     { 
      domain = "x.public"; 
      userNameToUse = z.ToString(); 
      local = "NO"; 
     } 
     else 
     { 
      domain = "x.local"; 
      userNameToUse = z.ToString(); 
      local = "YES"; 
     } 

     if (DoesUserExist (userNameToUse) == true) 
     { 
      if (isActive(userNameToUse) == true) 
      { 
       try 
       { 
        DirectoryEntry entry = new DirectoryEntry(ldappath, userNameToUse, _pwd); 
        object nativeObject = entry.NativeObject; 
        var GUIDID = ""; 

        using (var domainContext = new PrincipalContext(ContextType.Domain, domain)) 
        { 
         using (var user = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse)) 
         { 
          if (user != null) 
          { 
           GUIDID = user.Guid.ToString(); 
          } 
         } 
         message = "Successfully authenticated:" + GUIDID; 
        } 
       } 
       catch (DirectoryServicesCOMException) 
       { 
        message = "Invalid password."; 
       } 
      } 
      else 
      { 
       message = "Account is disabled"; 
      } 
     } 
     else 
     { 
      message = "There's an issue with your account."; 
     } 
     return message;  
    } 

    #endregion 
} 
} 

Если имя пользователя существует в DMZ н.э. он возвращает истину иначе она вернет ложь. Тем не менее, будут пользователи, которые будут существовать только в производстве AD, но не будут иметь записи в DMZ. Так как я построил ONE WAY доверие я должен быть в состоянии сделать это:

[email protected] для производства и [email protected] Однако, даже если я указать полностью имя пользователя, если запись не существует в DMZ нашей эры он возвращает нуль, хотя она существует в производстве ОБЪЯВЛЕНИЕ.

Любое предложение о том, как я могу аутентифицировать всех через DMZ AD, используя учетную запись webservices, которая имеет полное разрешение на производство AD?

Примечание при необходимости я могу предоставить остальную часть кода ... *

Благодаря

+0

Какой пользователь используется для запуска вышеуказанной программы? Вы должны использовать учетные данные из AD продукта, чтобы получить доступ к AD. Каков формат 'userName' и содержимого' domain'? – baldpate

+0

Это будет каждый пользователь. У меня есть учетная запись службы в обоих AD. Типичными именами пользователей будут 'sjohns', которые будут проверены против производства и' sjohns @ mail.com', которые будут проверены против DMZ. – smr5

+0

Нет предложений? – smr5

ответ

0

Какова стоимость домена в PrincipalContext? Если вы еще этого не сделали, вам нужно будет использовать правильный домен для пользователя, которого вы ищете, для пользователя вашего текущего кода. PrincipalContext не поддерживает поиск по доменам в вашем лесу.

Это example с помощью службы DirectorySearch.

+0

Благодарим вас за ответ. Я добавил весь код. Сначала вызывается эта функция 'isAuthenticated'. – smr5

+0

Итак, две вещи ... – codingChris

+0

Неправильно отредактировал достаточно быстро ... 1. У вас есть тесты? Если вы можете пройти через этот код, вы, вероятно, можете точно определить, где проблема и что происходит. 2. Я думаю, после того, как мы пройдем проверку имен пользователей, вам понадобится использовать DirectorySearcher в методе DoUserExist. Я не думаю, что PrincipalContext будет работать, чтобы добраться до локального домена. К сожалению, у меня нет такой установки, как ваша, чтобы протестировать. – codingChris

0

В коде есть несколько вопросов, я говорю только о крупных.

  1. В методе DoesUserExist вы используете учетную запись службы (нет учетных данных не передается в PrincipalContext) запрашивать оба домена. Но в методе isActive у вас разные учетные данные для разных доменов. Итак, у нас есть 3 учетных данных для 2 доменов ...

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

  2. Для 1-полосной доверие (например. А доверяет B), счета в B должен быть в состоянии получить доступ как домен A и B.

    Может быть, вы можете просто использовать учетную запись в доверенном домене в качестве учетной записи службы. Затем используйте учетную запись службы (от имени пользователя и пароля), чтобы выполнить весь доступ к AD. Поэтому вам даже не нужно вводить пароль в свой код.

  3. В isActive, откуда берет «66050»?
    66060 - 10202 в шестнадцатеричном виде, что означает (1) пользователя, (2) отключено и (3) не истекает пароль.

    Чтобы проверить, включена ли учетная запись, проверьте только бит ACCOUNTDISABLE (0x0002). Для включения должно быть 0.

  4. Вы уже получили UserPrincipal в DoesUserExist. Можно просто проверить включен, посмотрев на UserPrincipal.Enabled.

Мне нужно сделать обзор кода в моей повседневной работе. Теперь я делаю это также в Stack Overflow ... :)

+0

благодарю вас за ответ. Я только начал писать этот код, и он, скорее всего, будет меняться. Моя главная цель здесь - выполнить «Аутентификация» для предоставленных «username» и «password».Например, 'A (dmz)' trusts 'B (production)' и user 'jsmith' существует только в' B', но аутентификация должна выполняться с использованием 'A'. Какой подход я должен принять? Благодарю. – smr5

Смежные вопросы