Web Api 中的自签名证书始终为空
Posted
技术标签:
【中文标题】Web Api 中的自签名证书始终为空【英文标题】:Self Signed Certificate is always null in Web Api 【发布时间】:2017-08-31 23:26:21 【问题描述】:我在这个问题上花了整整一天,除了在这里问我的伙伴之外别无他法。
我们有一个接受 X509 证书的 web api,但是下面的代码在本地主机和开发服务器上总是给我 null。
以下是我获取证书的代码:
var certificate = actionContext.Request.GetClientCertificate();
我创建了一个ActionFilterAttribute
,在它的OnActionExecuting
中,我正在尝试获取上面提到的客户端证书。
在此之前,我按照this link 上的说明使用 Windows PowerShell 创建了证书:
我使用的命令是这样的:
New-SelfSignedCertificate -DnsName "localhost", "atp api" -CertStoreLocation "cert:\LocalMachine\My"
证书已创建,我确保它在受信任的证书中。 然后从我的示例客户端应用程序中,我使用以下代码将证书发送到我的 Web API:
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var certCollection = store.Certificates.Find(X509FindType.FindByIssuerName, "localhost", false);
var cert = certCollection[0];
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://localhost:44308/dk");
request.ClientCertificates.Add(cert);
request.Method = "POST";
string postData = "<string xmlns='http://schemas.microsoft.com/2003/10/Serialization/'>sample string 1</string>";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
//request.ContentType = "application/xml";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
store.Close();
但是在我的 Web API 证书中执行此代码时为空。我认为可能是因为 localhost,我在开发服务器上部署了 web api,证书仍然为空。
我也尝试从指定的 windows 位置而不是从商店获取证书,结果是一样的。
我用谷歌搜索了很多次,但没有任何帮助。
【问题讨论】:
我刚刚按照这个分步指南创建证书,但结果相同:blog.davidchristiansen.com/2016/09/… 【参考方案1】:您需要在 web.config 中添加这些行以强制 IIS 启动 SSL 证书协商:
<system.webServer>
<!-- things ... -->
<security>
<access sslFlags="SslNegotiateCert" />
</security>
<!-- things -->
</system.webServer>
【讨论】:
另外,我认为这与在 IIS 中设置 sll 设置相同。【参考方案2】:为您的request
设置ServerCertificateValidationCallback
属性:
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
ServerCertificateValidationCallback 是一种验证服务器证书的方法。因此request
将忽略证书错误。
如果您使用低于 v4.5 的 .NET Framework,您可以为
ServicePointManager.ServerCertificateValidationCallback。如果您愿意,您可以检查您的证书的自定义验证。
【讨论】:
我不想忽略证书错误,我想在服务器端获取证书。 在这种情况下尝试查看HttpWebRequest.ServicePoint.Certificate
属性。详细示例见here。【参考方案3】:
您可以在 iis 中更改 SSL 设置以接受证书而不是忽略它。
【讨论】:
设置后会出现禁止错误吗?或者证书仍然为空 您必须创建具有基本权限的证书,尝试创建自签名证书并提及服务器身份验证和客户端身份验证的密钥用法。您可以使用 open ssl 生成证书。 jamielinux.com/docs/openssl-certificate-authority/… 我使用 IIS 创建了自签名证书,但现在我收到“附加信息:底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系。” 问题出在证书的创建上。我认为我没有准确地创建证书。我也尝试过使用 Windows 的 New-SelfsignedCertificate 脚本。但问题仍然存在。 @muhammadkashif 不要忘记在本地计算机或当前用户的证书存储(受信任的根证书颁发机构)中导入您的证书。然后通过启动 certlm.msc 或 certmgr.msc 查看证书属性。无效或不受信任的证书可能是您出错的原因。【参考方案4】:您需要像 Spilarix 所述将<security><access sslFlags="SslNegotiateCert" /></security>
添加到您的 Web 配置文件中,并从服务器证书导出证书并安装它并将其用于客户端,以便客户端具有基于服务器证书的证书(和可以验证)但单独的证书(我知道它们都在同一台机器上)。这应该可以解决您的问题
【讨论】:
Certificates.Find 方法确实找到了证书,我成功地将它添加到请求中。但在服务器端它始终为空。以上是关于Web Api 中的自签名证书始终为空的主要内容,如果未能解决你的问题,请参考以下文章