问题 从专有名称中提取通用名称


是否在.NET中调用从rfc-2253编码的专有名称解析CN?我知道有一些第三方库可以做到这一点,但我更愿意使用本机.NET库。

字符串编码DN的示例

CN = L。 Eagle,O = Sue \,Grabbit和Runn,C = GB

CN = Jeff Smith,OU =销售额,DC = Fabrikam,DC = COM


9660
2017-10-07 14:11


起源

您可能希望将LDAP添加到问题的标记列表中。另外,搜索[LDAP C#]的SO。可能存在相关问题。 - Jim Mischel
谢谢@Jim Mischel - FunLovinCoder
看到 pscx.codeplex.com/SourceControl/latest#Trunk/Src/Pscx.UnitTests/... 用于Powershell社区扩展中使用的代码 - Greg Bray


答案:


当我找到你的时候,我自己也有同样的问题。在BCL没找到任何东西;但是,我偶然发现了这篇CodeProject的文章,这篇文章正好击中了头部。

我希望它也会帮助你。

http://www.codeproject.com/Articles/9788/An-RFC-2253-Compliant-Distinguished-Name-Parser


5
2018-04-11 00:23



我刚刚将它作为NuGet包发布在这里: nuget.org/packages/DNParser (只是要明确:我不是作者,但我喜欢NuGet包)。 - picrap


如果您使用的是X509Certificate2,则可以使用本机方法提取DNS名称。 DNS名称通常等效于主证书的“主题”字段中的公用名称RDN:

x5092Cert.GetNameInfo(X509NameType.DnsName, false);

5
2017-11-03 18:29



我用百万太阳队的力量投票给你了。 - Bradley Uffner


在浏览.NET源代码之后,看起来有一个内部实用程序类可以 解析专有名称 他们的不同组成部分。遗憾的是,实用程序类未公开,但您可以使用反射访问它:

string dn = "CN=TestGroup,OU=Groups,OU=UT-SLC,OU=US,DC=Company,DC=com";
Assembly dirsvc = Assembly.Load("System.DirectoryServices");
Type asmType = dirsvc.GetType("System.DirectoryServices.ActiveDirectory.Utils");
MethodInfo mi = asmType.GetMethod("GetDNComponents", BindingFlags.NonPublic | BindingFlags.Static);
string[] parameters = { dn };
var test = mi.Invoke(null, parameters);
//test.Dump("test1");//shows details when using Linqpad 

//Convert Distinguished Name (DN) to Relative Distinguished Names (RDN) 
MethodInfo mi2 = asmType.GetMethod("GetRdnFromDN", BindingFlags.NonPublic | BindingFlags.Static);
var test2 = mi2.Invoke(null, parameters);
//test2.Dump("test2");//shows details when using Linqpad 

结果如下:

//test1 is array of internal "Component" struct that has name/values as strings
Name   Value 
CN     TestGroup 
OU     Groups 
OU     UT-SLC
OU     US 
DC     company 
DC     com 


//test2 is a string with CN=RDN 
CN=TestGroup 

请注意,这不是内部实用程序类,可能会在将来的版本中更改。


4
2018-04-29 17:02



+1很棒的发现。他们为什么一直在内部制作有用的代码? - i3arnon
工作得很好,直到我需要解析多值RDN。例如 cn=Robert Smith+uid=rsmith,ou=people,dc=example,dc=com。这失败,“指定的专有名称格式无效”。 - Nathanial Woolls


Win32功能有效吗?您可以使用PInvoke DsGetRdnW。有关代码,请参阅我对其他问题的回答: https://stackoverflow.com/a/11091804/628981


3
2017-11-21 15:51





在这里加我的两分钱。如果您首先了解最终将要执行的业务规则,那么此实现将“最佳” 多少 RFC将在您的公司实施。

private static string ExtractCN(string distinguishedName)
{
    // CN=...,OU=...,OU=...,DC=...,DC=...
    string[] parts;

    parts = distinguishedName.Split(new[] { ",DC=" }, StringSplitOptions.None);
    var dc = parts.Skip(1);

    parts = parts[0].Split(new[] { ",OU=" }, StringSplitOptions.None);
    var ou = parts.Skip(1);

    parts = parts[0].Split(new[] { ",CN=" }, StringSplitOptions.None);
    var cnMulti = parts.Skip(1);

    var cn = parts[0];

    if (!Regex.IsMatch(cn, "^CN="))
        throw new CustomException(string.Format("Unable to parse distinguishedName for commonName ({0})", distinguishedName));

    return Regex.Replace(cn, "^CN=", string.Empty);
}

1
2017-12-20 17:26





如果订单不确定,我这样做:

private static string ExtractCN(string dn)
{
    string[] parts = dn.Split(new char[] { ',' });

    for (int i = 0; i < parts.Length; i++)
    {
        var p = parts[i];
        var elems = p.Split(new char[] { '=' });
        var t = elems[0].Trim().ToUpper();
        var v = elems[1].Trim();
        if (t == "CN")
        {
            return v;
        }
    }
    return null;
}

1
2018-04-15 09:50



包含逗号的常用名称将破坏这一点。例: CN=Martin Luther King\, Jr. 将错误地返回 Martin Luther King - Eric Eskildsen


你能不能只检索CN属性值?

正如你正确指出的那样,使用其他人的类,因为有很多有趣的边缘情况(转义逗号,转义其他字符),这使得解析DN看起来很容易,但实际上相当棘手。

我通常使用Novell(Now NetID)Identity Manager附带的Java类。所以这没有用。


0
2017-10-09 19:28



No无法从LDAP条目中获取属性值 - 只需要使用证书即可。不管怎么说,还是要谢谢你。 - FunLovinCoder
@swisstony:啊,你有一个证书DN。这仍然是正确解析的基本问题。 - geoffc
是的,仍然是DN同样的问题。看起来我可能不得不使用像bouncycastle这样的第三方库...... - FunLovinCoder


这个怎么样:

string cnPattern = @"^CN=(?<cn>.+?)(?<!\\),";
string dn        = @"CN=Doe\, John,OU=My OU,DC=domain,DC=com";

Regex re = new Regex(cnPattern);          
Match m  = re.Match(dn);

if (m.Success)
{
  // Item with index 1 returns the first group match.
  string cn = m.Groups[1].Value;
}

改编自 用于提取Active Directory区别名称部分的Powershell正则表达式


0
2017-10-28 19:40



这个正则表达式有问题:CN不能保证在DN的开头,你假设会有一个名称部分 之后 CN,它不处理引用的字符串。示例DN: O=Acme, OU=Acme, CN="My super, ""Great"" CN" - Cocowalla
为什么CN不在起步?谁告诉你CN可以在中间?在您的示例中,必须转义逗号,就像引号字符一样。 DN中不使用引号来隔离DN部件值。 - Alek Davis
检查RFC2253的第4部分 - 它声明实现必须允许值被引号括起来,并且在引号内部不需要转义逗号 - Cocowalla
忘了回答关于CN的立场 - 我将通过我在现实生活中看到的经验来回答。您还可以在其中查看此示例 这个 文件和 这个 页 - Cocowalla