.NET LDAP路径实用程序(C#)
是否有用于LDAP路径操作的.NET库?.NET LDAP路径实用程序(C#),c#,.net,active-directory,ldap,C#,.net,Active Directory,Ldap,是否有用于LDAP路径操作的.NET库? 我想要一些与System.IO.Path等效的东西,例如允许做类似的事情 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目录服务”;我已经做过这方面的工作,并且做了一
我想要一些与
System.IO.Path
等效的东西,例如允许做类似的事情
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) 例如,在库中调用一个函数,将字符串拆分为逗号。据我所知,不是这样的,甚至在最新的.NET 3.5 Active Directory命名空间中也不是这样 您可以在目录本身中导航层次结构(转到父目录等),但需要通过
DirectoryEntry
绑定到Active directory等
还有,但这实际上更多的是“将此名称更改为另一个名称”,例如,从用户主体名称更改为相对DN-同样,它需要连接到AD中的DirectoryEntry
我最感兴趣的是找到这样一个库,但到目前为止,我还没有听说过这样一个库——无论是在.NET还是其他语言中,真的
回到我“繁重”的广告编程时代,我有自己的一套LDAP路径操作例程(在Delphi中)——基本上就是字符串解析和处理
Marc我使用了两个基于Win32方法DsGetRdnW、DsQuoteRdnValueW和DsUnquoteRdnValueW的实用程序类:
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();
}
}
}
使用系统;
使用系统组件模型;
使用System.Collections.Generic;
使用System.Runtime.InteropServices;
命名空间非托管代码
{
公营平沃克
{
#区域常数
public const int ERROR_SUCCESS=0;
public const int ERROR_BUFFER_OVERFLOW=111;
#端区常数
#区域DN解析
[DllImport(“ntdsapi.dll”,CharSet=CharSet.Unicode)]
受保护的静态外部int DsGetRdnW(
参考IntPtr ppDN,
参考int pcDN,
输出IntPtr ppKey,
out int pcKey,
输出IntPtr ppVal,
out int pcVal
);
public static KeyValuePair GetName(字符串区分名称)
{
IntPtr pDistinguishedName=Marshal.StringToHGlobalUni(区分名称);
尝试
{
IntPtr pDN=pDistinguishedName,pKey,pVal;
int cDN=区分名称.长度,cKey,cVal;
int lastError=DSGETRNW(参考pDN、参考cDN、输出pKey、输出cKey、输出pVal、输出cVal);
如果(lastError==错误\u成功)
{
字符串键,值;
if(cKey<1)
{
key=string.Empty;
}
其他的
{
key=Marshal.PtrToStringUni(pKey,cKey);
}
if(cVal<1)
{
value=string.Empty;
}
其他的
{
值=Marshal.PtrToStringUni(pVal,cVal);
}
返回新的KeyValuePair(键,值);
}
其他的
{
抛出新的Win32Exception(lastError);
}
}
最后
{
FreeHGlobal元帅(pDistinguishedName);
}
}
公共静态IEnumerable ParseDN(字符串区分名称)
{
列表0);
返回组件;
}
最后
{
FreeHGlobal元帅(pDistinguishedName);
}
}
[DllImport(“ntdsapi.dll”,CharSet=CharSet.Unicode)]
受保护的静态外部int DSQUOTERDNVALUE(
int cunQuotedDNValueLength,
字符串psUnquotedRdnValue,
ref int pcQuotedRdnValueLength,
IntPtr psQuotedRdnValue
);
公共静态字符串QuoteRDN(字符串rdn)
{
if(rdn==null)返回null;
int initialLength=rdn.Length;
int quotedLength=0;
IntPtr pQuotedRDN=IntPtr.0;
int lastError=DsQuoteRdnValueW(初始长度、rdn、ref quotedLength、PQQUOTEDRDN);
开关(最后一个错误)
{
案例错误\u成功:
{
返回字符串。空;
}
案例错误\缓冲区\溢出:
{
break;//继续
}
违约:
{
抛出新的Win32Exception(lastError);
}
}
pQuotedRDN=Marshal.AllocHGlobal(quotedLength*Unicode.CharSize);
尝试
{
lastError=DsQuoteRdnValueW(初始长度、rdn、ref quotedLength、PQQUOTEDRDN);
开关(最后一个错误)
{
案例错误\u成功:
{
返回Marshal.PtrToStringUni(pQuotedRDN,quotedLength);
}
违约:
{
抛出新的Win32Exception(lastError);
}
}
}
最后
{
如果(pquoterdn!=IntPtr.Zero)
{
弗里赫全球元帅(PQUOTERDN);
}
}
}
[DllImport(“ntdsapi.dll”,CharSet=CharSet.Unicode)]
受保护静态扩展
var uri = new Uri(SomeDomainURI);
var scheme = uri.Scheme; // == "LDAP" or "LDAPS" usually
var domainHost = uri.Host;
var path = uri.AbsolutePath.TrimStart('/');
var dn = new DN(uri.AbsolutePath.TrimStart('/'));