2009-09-16 10 views
3

LDAP 경로 조작을위한 .NET 라이브러리가 있습니까?
System.IO.Path에 해당하는 항목을 갖고 싶습니다. 예 :.NET LDAP 경로 유틸리티 (C#)

string ou1 = LDAPPath.Combine("OU=users","DC=x,DC=y"); 
string ou2 = LDAPPath.Parent("CN=someone,OU=users,DC=x,DC=y"); 

그렇지 않으면 .NET에서 LDAP 고유 이름을 처리하는 일반적인 방법은 무엇입니까?

내 질문을 명확히하려면 : 일반적으로 ".NET의 디렉토리 서비스"에 대해 묻지 않습니다. 나는 이미 그 작업을 수행하고 일부 작업을 수행하기 위해 일부 프로그램을 수행했습니다. 내가 누락 된 기분이 경로를 조작하고 고유 이름을 구문 분석하는 등의 적절한 방법이 있으며 꽤 일반적인 필요가 있기 때문에 쉼표 (1)로 문자열을 분할하는 것보다 더 깨끗한 방법이 필요합니다. .

(1)과 같은 예를 들어, 쉼표

나의 지식
+0

Powershell Community Extensions –

+0

에서 사용되는 코드에 대해 https://pscx.codeplex.com/SourceControl/latest#Trunk/Src/Pscx.UnitTests/DirectoryServices/DirectoryServicesTest.cs 및 관련 질문 http : // stackoverflow를 참조하십시오. .com/a/23370901/17373 –

답변

2

아냐, 문자열 분할 라이브러리에서 함수 호출 - 심지어 Active Directory에 대한 가장 최근의 .NET 3.5 네임 스페이스를.

디렉토리 자체에서 계층을 탐색 할 수 있습니다 (예 : 부모 등으로 이동). Active Directory는 DirectoryEntry을 통해 제공됩니다.

그리고 나서 NameTranslate API이 있지만 실제로는 "이 이름을 다른 이름으로 변경"합니다. 사용자 교장 이름에서 상대 DN으로 변경 - 다시 AD에 DirectoryEntry에 대한 연결이 필요합니다.

저는 이러한 라이브러리를 찾는 데 가장 관심이 있었지만 지금까지 .NET에 대해서도 다른 언어로는 들어 본 적이 없었습니다.

"내구성이 강한"AD 프로그래밍 시대에 필자는 자신 만의 LDAP 경로 조작 루틴 (델파이)을 사용 했었습니다. 기본적으로 문자열 파싱 및 처리입니다.

마크

내가 DsGetRdnW, DsQuoteRdnValueW 및 DsUnquoteRdnValueW는 Win32 방법을 기반으로 유틸리티 클래스의 몇 가지를 사용
+0

안녕하세요 marc_s, 답장을 보내 주셔서 감사합니다 ... 내가 추측 한 것보다 다소 적습니다. –

5

:

using System; 
using System.ComponentModel; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 

namespace UnmanagedCode 
{ 
    public class PInvoke 
    { 
     #region Constants 
     public const int ERROR_SUCCESS = 0; 
     public const int ERROR_BUFFER_OVERFLOW = 111; 
     #endregion Constants 

     #region DN Parsing 
     [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] 
     protected static extern int DsGetRdnW(
      ref IntPtr ppDN, 
      ref int pcDN, 
      out IntPtr ppKey, 
      out int pcKey, 
      out IntPtr ppVal, 
      out int pcVal 
     ); 

     public static KeyValuePair<string, string> GetName(string distinguishedName) 
     { 
      IntPtr pDistinguishedName = Marshal.StringToHGlobalUni(distinguishedName); 
      try 
      { 
       IntPtr pDN = pDistinguishedName, pKey, pVal; 
       int cDN = distinguishedName.Length, cKey, cVal; 

       int lastError = DsGetRdnW(ref pDN, ref cDN, out pKey, out cKey, out pVal, out cVal); 

       if(lastError == ERROR_SUCCESS) 
       { 
        string key, value; 

        if(cKey < 1) 
        { 
         key = string.Empty; 
        } 
        else 
        { 
         key = Marshal.PtrToStringUni(pKey, cKey); 
        } 

        if(cVal < 1) 
        { 
         value = string.Empty; 
        } 
        else 
        { 
         value = Marshal.PtrToStringUni(pVal, cVal); 
        } 

        return new KeyValuePair<string, string>(key, value); 
       } 
       else 
       { 
        throw new Win32Exception(lastError); 
       } 
      } 
      finally 
      { 
       Marshal.FreeHGlobal(pDistinguishedName); 
      } 
     } 

     public static IEnumerable<KeyValuePair<string, string>> ParseDN(string distinguishedName) 
     { 
      List<KeyValuePair<string, string> components = new List<KeyValuePair<string, string>>(); 
      IntPtr pDistinguishedName = Marshal.StringToHGlobalUni(distinguishedName); 
      try 
      { 
       IntPtr pDN = pDistinguishedName, pKey, pVal; 
       int cDN = distinguishedName.Length, cKey, cVal; 

       do 
       { 
        int lastError = DsGetRdnW(ref pDN, ref cDN, out pKey, out cKey, out pVal, out cVal); 

        if(lastError = ERROR_SUCCESS) 
        { 
         string key, value; 

         if(cKey < 0) 
         { 
          key = null; 
         } 
         else if(cKey == 0) 
         { 
          key = string.Empty; 
         } 
         else 
         { 
          key = Marshal.PtrToStringUni(pKey, cKey); 
         } 

         if(cVal < 0) 
         { 
          value = null; 
         } 
         else if(cVal == 0) 
         { 
          value = string.Empty; 
         } 
         else 
         { 
          value = Marshal.PtrToStringUni(pVal, cVal); 
         } 

         components.Add(new KeyValuePair<string, string>(key, value)); 

         pDN = (IntPtr)(pDN.ToInt64() + UnicodeEncoding.CharSize); //skip over comma 
         cDN--; 
        } 
        else 
        { 
         throw new Win32Exception(lastError); 
        } 
       } while(cDN > 0); 

       return components; 
      } 
      finally 
      { 
       Marshal.FreeHGlobal(pDistinguishedName); 
      } 
     } 

     [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] 
     protected static extern int DsQuoteRdnValueW(
      int cUnquotedRdnValueLength, 
      string psUnquotedRdnValue, 
      ref int pcQuotedRdnValueLength, 
      IntPtr psQuotedRdnValue 
     ); 

     public static string QuoteRDN(string rdn) 
     { 
      if (rdn == null) return null; 

      int initialLength = rdn.Length; 
      int quotedLength = 0; 
      IntPtr pQuotedRDN = IntPtr.Zero; 

      int lastError = DsQuoteRdnValueW(initialLength, rdn, ref quotedLength, pQuotedRDN); 

      switch (lastError) 
      { 
       case ERROR_SUCCESS: 
        { 
         return string.Empty; 
        } 
       case ERROR_BUFFER_OVERFLOW: 
        { 
         break; //continue 
        } 
       default: 
        { 
         throw new Win32Exception(lastError); 
        } 
      } 

      pQuotedRDN = Marshal.AllocHGlobal(quotedLength * UnicodeEncoding.CharSize); 

      try 
      { 
       lastError = DsQuoteRdnValueW(initialLength, rdn, ref quotedLength, pQuotedRDN); 

       switch(lastError) 
       { 
        case ERROR_SUCCESS: 
         { 
          return Marshal.PtrToStringUni(pQuotedRDN, quotedLength); 
         } 
        default: 
         { 
          throw new Win32Exception(lastError); 
         } 
       } 
      } 
      finally 
      { 
       if(pQuotedRDN != IntPtr.Zero) 
       { 
        Marshal.FreeHGlobal(pQuotedRDN); 
       } 
      } 
     } 


     [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] 
     protected static extern int DsUnquoteRdnValueW(
      int cQuotedRdnValueLength, 
      string psQuotedRdnValue, 
      ref int pcUnquotedRdnValueLength, 
      IntPtr psUnquotedRdnValue 
     ); 

     public static string UnquoteRDN(string rdn) 
     { 
      if (rdn == null) return null; 

      int initialLength = rdn.Length; 
      int unquotedLength = 0; 
      IntPtr pUnquotedRDN = IntPtr.Zero; 

      int lastError = DsUnquoteRdnValueW(initialLength, rdn, ref unquotedLength, pUnquotedRDN); 

      switch (lastError) 
      { 
       case ERROR_SUCCESS: 
        { 
         return string.Empty; 
        } 
       case ERROR_BUFFER_OVERFLOW: 
        { 
         break; //continue 
        } 
       default: 
        { 
         throw new Win32Exception(lastError); 
        } 
      } 

      pUnquotedRDN = Marshal.AllocHGlobal(unquotedLength * UnicodeEncoding.CharSize); 

      try 
      { 
       lastError = DsUnquoteRdnValueW(initialLength, rdn, ref unquotedLength, pUnquotedRDN); 

       switch(lastError) 
       { 
        case ERROR_SUCCESS: 
         { 
          return Marshal.PtrToStringUni(pUnquotedRDN, unquotedLength); 
         } 
        default: 
         { 
          throw new Win32Exception(lastError); 
         } 
       } 
      } 
      finally 
      { 
       if(pUnquotedRDN != IntPtr.Zero) 
       { 
        Marshal.FreeHGlobal(pUnquotedRDN); 
       } 
      } 
     } 
     #endregion DN Parsing 
    } 

    public class DNComponent 
    { 
     public string Type { get; protected set; } 
     public string EscapedValue { get; protected set; } 
     public string UnescapedValue { get; protected set; } 
     public string WholeComponent { get; protected set; } 

     public DNComponent(string component, bool isEscaped) 
     { 
      string[] tokens = component.Split(new char[] { '=' }, 2); 
      setup(tokens[0], tokens[1], isEscaped); 
     } 

     public DNComponent(string key, string value, bool isEscaped) 
     { 
      setup(key, value, isEscaped); 
     } 

     private void setup(string key, string value, bool isEscaped) 
     { 
      Type = key; 

      if(isEscaped) 
      { 
       EscapedValue = value; 
       UnescapedValue = PInvoke.UnquoteRDN(value); 
      } 
      else 
      { 
       EscapedValue = PInvoke.QuoteRDN(value); 
       UnescapedValue = value; 
      } 

      WholeComponent = Type + "=" + EscapedValue; 
     } 

     public override bool Equals(object obj) 
     { 
      if (obj is DNComponent) 
      { 
       DNComponent dnObj = (DNComponent)obj; 
       return dnObj.WholeComponent.Equals(this.WholeComponent, StringComparison.CurrentCultureIgnoreCase); 
      } 
      return base.Equals(obj); 
     } 

     public override int GetHashCode() 
     { 
      return WholeComponent.GetHashCode(); 
     } 
    } 

    public class DistinguishedName 
    { 
     public DNComponent[] Components 
     { 
      get 
      { 
       return components.ToArray(); 
      } 
     } 

     private List<DNComponent> components; 
     private string cachedDN; 

     public DistinguishedName(string distinguishedName) 
     { 
      cachedDN = distinguishedName; 
      components = new List<DNComponent>(); 
      foreach (KeyValuePair<string, string> kvp in PInvoke.ParseDN(distinguishedName)) 
      { 
       components.Add(new DNComponent(kvp.Key, kvp.Value, true)); 
      } 
     } 

     public DistinguishedName(IEnumerable<DNComponent> dnComponents) 
     { 
      components = new List<DNComponent>(dnComponents); 
      cachedDN = GetWholePath(","); 
     } 

     public bool Contains(DNComponent dnComponent) 
     { 
      return components.Contains(component); 
     } 

     public string GetDNSDomainName() 
     { 
      List<string> dcs = new List<string>(); 
      foreach (DNComponent dnc in components) 
      { 
       if(dnc.Type.Equals("DC", StringComparison.CurrentCultureIgnoreCase)) 
       { 
        dcs.Add(dnc.UnescapedValue); 
       } 
      } 
      return string.Join(".", dcs.ToArray()); 
     } 

     public string GetDomainDN() 
     { 
      List<string> dcs = new List<string>(); 
      foreach (DNComponent dnc in components) 
      { 
       if(dnc.Type.Equals("DC", StringComparison.CurrentCultureIgnoreCase)) 
       { 
        dcs.Add(dnc.WholeComponent); 
       } 
      } 
      return string.Join(",", dcs.ToArray()); 
     } 

     public string GetWholePath() 
     { 
      return GetWholePath(","); 
     } 

     public string GetWholePath(string separator) 
     { 
      List<string> parts = new List<string>(); 
      foreach (DNComponent component in components) 
      { 
       parts.Add(component.WholeComponent); 
      } 
      return string.Join(separator, parts.ToArray()); 
     } 

     public DistinguishedName GetParent() 
     { 
      if(components.Count == 1) 
      { 
       return null; 
      } 
      List<DNComponent> tempList = new List<DNComponent>(components); 
      tempList.RemoveAt(0); 
      return new DistinguishedName(tempList); 
     } 

     public override bool Equals(object obj) 
     { 
      if(obj is DistinguishedName) 
      { 
       DistinguishedName objDN = (DistinguishedName)obj; 
       if (this.Components.Length == objDN.Components.Length) 
       { 
        for (int i = 0; i < this.Components.Length; i++) 
        { 
         if (!this.Components[i].Equals(objDN.Components[i])) 
         { 
          return false; 
         } 
        } 
        return true; 
       } 
       return false; 
      } 
      return base.Equals(obj); 
     } 

     public override int GetHashCode() 
     { 
      return cachedDN.GetHashCode(); 
     } 
    } 
} 
0

.NET에는 LDAP 경로 파서가 없지만은있다 URI 파서. 단순히 구문 분석을 필요로하는 사람들을 위해 "LDAP : // 도메인/..."경로는 다음과 같은 몇 가지 세부 사항을 얻을 수 있으며, System.Uri 클래스를 사용하여 다음을 수행 할 수 있습니다

var uri = new Uri(SomeDomainURI); 
var scheme = uri.Scheme; // == "LDAP" or "LDAPS" usually 
var domainHost = uri.Host; 
var path = uri.AbsolutePath.TrimStart('/'); 

당신도 할 수 this DN parser 사용하는 경우 경로 분석하는 대신 다음을 수행하십시오

var dn = new DN(uri.AbsolutePath.TrimStart('/')); 

내가 .NET 지금까지이 있었다한다 동의하면서이 (! 부끄러운)이 내 요구에 주위에 적어도 확인 작업이었다가 완벽하지 불구하고, 나는 그것이 모든 사람을 위해 충분히 강할 것이라는 점을 의심한다.