C# 如何从客户端证书中读取公共名称?

C# 如何从客户端证书中读取公共名称?,c#,.net,client-certificates,C#,.net,Client Certificates,我们的应用程序需要一段数据,它包含在客户端证书的公共名称中。目前,我正在尝试从HttpContext.Current.Request.ClientCertificate获取它。我怎么读出来?可悲的是,我试图编写这个盲代码,同时我想知道为什么SoapUI不发送证书,所以除了阅读MSDN上的对象和浏览空属性之外,我没有做过很多尝试,但我不确定我在寻找什么。总而言之,我需要做什么才能从该证书中提取通用名称?TIA我对证书略知一二。这是我的工作流程: 我从: 这让我想到: (作为返回类型) 它似乎有几

我们的应用程序需要一段数据,它包含在客户端证书的公共名称中。目前,我正在尝试从HttpContext.Current.Request.ClientCertificate获取它。我怎么读出来?可悲的是,我试图编写这个盲代码,同时我想知道为什么SoapUI不发送证书,所以除了阅读MSDN上的对象和浏览空属性之外,我没有做过很多尝试,但我不确定我在寻找什么。总而言之,我需要做什么才能从该证书中提取通用名称?TIA

我对证书略知一二。这是我的工作流程:

我从:

这让我想到:

(作为返回类型)

它似乎有几个属性,但没有一个显式命名为公共名称

谷歌搜索:HttpClientCertificate通用名称:

其中包含一些代码:

//extracting Common name from certificate
Subject = cert.Subject.ToString();
然后去了:

其中:

如果指定的字符串没有子字段,HttpClientCertificate集合将返回以逗号分隔的子字段列表。例如,C=US,O=Msft

由于我所掌握的知识非常有限,我知道通用名=在这个列表中。目前我还没有实际的方法来测试这个,但是为您正在寻找的名称解析这个值应该不难

这是一个好问题(+1),我很高兴你问了它,因为它可能对未来的读者有用

我创建了一个,尽管它使用HttpWebRequest获取X509Certificate类,但它确实有一个Subject属性,该属性在www.google.com上为https返回以下值:

CN=www.google.com,O=googleinc,L=mountainview,S=California,C=US


因此,我倾向于相信HttpClientCertificate上的主题将是相同的值(知道CN意味着CommonName)。

我回答您的问题可能为时已晚,但我希望这将帮助其他正在寻找从证书中获取通用名称的方法的人

Dim store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
store.Open(OpenFlags.ReadOnly)
store.Certificates(0).GetNameInfo(X509NameType.SimpleName, False)
如果使用“主题”,可能需要删除其他不必要的信息。 例如,CN=localhost,OU=DepartmentName,O=CompanyName,L=Location,S=State,C=Country

Dim store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
store.Open(OpenFlags.ReadOnly)
store.Certificates(0).Subject
但是如果您使用下面的代码,您将得到“localhost”,它直接为您提供证书的通用名称

Dim store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
store.Open(OpenFlags.ReadOnly)
store.Certificates(0).GetNameInfo(X509NameType.SimpleName, False)
以下是供参考的链接:-

由于证书格式不同,您可能需要进行调整

下面是一些执行此操作的代码:

HttpClientCertificate theHttpCertificate = HttpContext.Current.Request.ClientCertificate; 
// split the subject into its parts
string[] subjectArray = theHttpCertificate.Subject.Split(',');
string[] nameParts;
string CN = string.Empty;
string firstName = string.Empty;
string lastName = string.Empty;

foreach (string item in subjectArray)
{
    string[] oneItem = item.Split('=');
    // Split the Subject CN information
    if (oneItem[0].Trim() == "CN")
    {
       CN = oneItem[1];
       if (CN.IndexOf(".") > 0)
       {// Split the name information
           nameParts = CN.Split('.');
           lastName = nameParts[0];
           firstName = nameParts[1];
        }
    }
}

只不过是林克的一架飞机

var kvs = cert.Subject.Split(',').Select(x => new KeyValuePair<string, string>(x.Split('=')[0], x.Split('=')[1])).ToList();
var kvs=cert.Subject.Split(',')。选择(x=>newkeyvaluepair(x.Split('=')[0],x.Split('=')[1])。ToList();

返回一个通用列表。不要在这里使用字典,因为主题可能包含重复的字段。

最好使用内置的GetNameInfo方法,使用名称类型和布尔标志

假设您使用此扩展方法:

[return:MaybeNull]
public static X509Certificate2? GetCodeSignCertificate(this Assembly asm)
{
    if (asm is null)
    {
        throw new ArgumentNullException(nameof(asm));
    }

    if (!File.Exists(asm.Location))
    {
        return null;
    }

    using var cert=System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromSignedFile(asm.Location);
    if (cert is null)
        return null;

    return new X509Certificate2(cert);
}
然后,您可以使用类中的类型获取证书,如下所示:

[TestMethod()]
public void TryGetCodeSigning()
{
    //var item = new Walter.CallStack();

    var item = new List<string>();
            
    using var cert = item.GetType().Assembly.GetCodeSignCertificate();
    Assert.IsNotNull(cert.GetNameInfo(X509NameType.SimpleName,true));

}
获取证书签名者的姓名

cert.GetNameInfo(X509NameType.SimpleName,false)

看看这是否适合您。

我感谢您的意见。请不要加入这帮人,他们一开始就认为OP没有努力寻找。我确实提到我不确定我在找什么。我搜索了大约45分钟,一直得到各种各样的答案。您的一个链接是“在web服务端从上下文中提取X509证书时出现问题”,我确实看到了该链接,但并没有遵循它,因为,老实说,它并没有确切地尖叫“这就是您要找的”。但至少,我很欣赏你说我懒惰的机智。我是认真地试图谦虚。我没有尝试太多是主观的,所以我不确定这是5分钟还是2小时,等等。我完全理解,我的工作流程不是以任何方式让你失望,只是为了解释我是如何得出答案的。是最后的评论让我有点烦,但看起来你把它删掉了。谢谢:)我还在调查,我喜欢这个问题:)同意。我希望在拿到真正的证书后再测试一下。由于某种原因,我一直得到一个空的对象。但这是另一个问题。因此,基于此,我编写了所有代码来抓取主题并解析它。测试完成后,我会报告并接受答案。请您详细说明您的答案,再添加一点关于您提供的解决方案的描述,好吗?很抱歉,答案很短。我已经编辑了我的答案,希望它能帮助其他人。我会修剪()键和值以去掉多余的空格。