C# 如何从客户端证书中读取公共名称?
我们的应用程序需要一段数据,它包含在客户端证书的公共名称中。目前,我正在尝试从HttpContext.Current.Request.ClientCertificate获取它。我怎么读出来?可悲的是,我试图编写这个盲代码,同时我想知道为什么SoapUI不发送证书,所以除了阅读MSDN上的对象和浏览空属性之外,我没有做过很多尝试,但我不确定我在寻找什么。总而言之,我需要做什么才能从该证书中提取通用名称?TIA我对证书略知一二。这是我的工作流程: 我从: 这让我想到: (作为返回类型) 它似乎有几个属性,但没有一个显式命名为公共名称 谷歌搜索:HttpClientCertificate通用名称: 其中包含一些代码:C# 如何从客户端证书中读取公共名称?,c#,.net,client-certificates,C#,.net,Client Certificates,我们的应用程序需要一段数据,它包含在客户端证书的公共名称中。目前,我正在尝试从HttpContext.Current.Request.ClientCertificate获取它。我怎么读出来?可悲的是,我试图编写这个盲代码,同时我想知道为什么SoapUI不发送证书,所以除了阅读MSDN上的对象和浏览空属性之外,我没有做过很多尝试,但我不确定我在寻找什么。总而言之,我需要做什么才能从该证书中提取通用名称?TIA我对证书略知一二。这是我的工作流程: 我从: 这让我想到: (作为返回类型) 它似乎有几
//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小时,等等。我完全理解,我的工作流程不是以任何方式让你失望,只是为了解释我是如何得出答案的。是最后的评论让我有点烦,但看起来你把它删掉了。谢谢:)我还在调查,我喜欢这个问题:)同意。我希望在拿到真正的证书后再测试一下。由于某种原因,我一直得到一个空的对象。但这是另一个问题。因此,基于此,我编写了所有代码来抓取主题并解析它。测试完成后,我会报告并接受答案。请您详细说明您的答案,再添加一点关于您提供的解决方案的描述,好吗?很抱歉,答案很短。我已经编辑了我的答案,希望它能帮助其他人。我会修剪()键和值以去掉多余的空格。