无法使用自签名客户端证书验证对 ASP.NET MVC3 服务的调用
Cannot authenticate a call to ASP.NET MVC3 service with a self-signed client certificate
我在带有 .NET Framework 4.5 的 IIS 7.5 中有一个 ASP.NET MVC3 服务 运行,我想在其中使用客户端证书保护对其中一个子路径的访问。对于该子路径,我制作了一个控制器,该控制器标有特制属性,该属性将访问请求客户端证书
public class CheckCertAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(
ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Headers.Add(
"CheckCertAttribute", "entered");
var cert = filterContext.HttpContext.Request.ClientCertificate;
// check the cert here, optionally return HTTP 403
}
}
最初正在调用 OnActionExecuting()
,但 Certificate
为空。结果我需要在 web.config:
中启用 SslNegotiateCert
<location path="PathOfInterest">
<system.webServer>
<security>
<access sslFlags="SslNegotiateCert"/>
</security>
</system.webServer>
</location>
执行此操作后,客户端始终会收到 HTTP 403,并且不再调用该属性。
客户端证书是自签名的并导出为 .pfx(带有私钥)所以我猜问题是一旦它到达服务器端服务器不喜欢它并拒绝接受它并且通过。客户端使用 HttpWebRequest
:
var cert = new X509Certificate2(pathToPfx, password);
var request = (HttpWebRequest)WebRequest.Create("https://my.company.com/PathOfInterest");
request.ClientCertificates.Add(cert);
request.GetResponse();
我之前已经使用过这种方法并且很有效。第一种情况是客户端证书不是自签名的,而是由中间证书签名的,而中间证书又由一些受信任的根授权机构签名——在这种情况下,我的服务配置非常相似,可以很好地接收它。第二种情况是使用自签名客户端证书进行 Azure 管理服务调用,但在这种情况下,我不知道服务器端是如何配置的。
因此我得出结论,证书的自签名性质使其成为 "not working"。我已经做了一些额外的事情 - 也许将一些东西添加到 web.config 或将证书添加到服务器端的某个证书存储中。我只是不知道这应该是什么。
如何使此设置生效?
IIS 尝试 "negotiate" 与客户端建立相互信任的连接,但由于客户端证书是自签名的,因此拒绝信任它。
您的选择:
- 使用知名证书颁发机构颁发的证书。这可行,但您必须每年左右重新颁发证书。
- 运行 您自己的 CA 基础设施,将其根 CA 证书添加到 "trusted root" 服务机器的证书存储中,并颁发用该根签名的证书(可能通过中间证书)。
- 将自签名证书添加到 "trusted root" 台服务机器中。 This may induce subtle yet serious security risks。我个人反对这个选项,因为它感觉很不安全。
- 切换到其他一些不使用客户端证书的身份验证方案。
我在带有 .NET Framework 4.5 的 IIS 7.5 中有一个 ASP.NET MVC3 服务 运行,我想在其中使用客户端证书保护对其中一个子路径的访问。对于该子路径,我制作了一个控制器,该控制器标有特制属性,该属性将访问请求客户端证书
public class CheckCertAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(
ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Headers.Add(
"CheckCertAttribute", "entered");
var cert = filterContext.HttpContext.Request.ClientCertificate;
// check the cert here, optionally return HTTP 403
}
}
最初正在调用 OnActionExecuting()
,但 Certificate
为空。结果我需要在 web.config:
SslNegotiateCert
<location path="PathOfInterest">
<system.webServer>
<security>
<access sslFlags="SslNegotiateCert"/>
</security>
</system.webServer>
</location>
执行此操作后,客户端始终会收到 HTTP 403,并且不再调用该属性。
客户端证书是自签名的并导出为 .pfx(带有私钥)所以我猜问题是一旦它到达服务器端服务器不喜欢它并拒绝接受它并且通过。客户端使用 HttpWebRequest
:
var cert = new X509Certificate2(pathToPfx, password);
var request = (HttpWebRequest)WebRequest.Create("https://my.company.com/PathOfInterest");
request.ClientCertificates.Add(cert);
request.GetResponse();
我之前已经使用过这种方法并且很有效。第一种情况是客户端证书不是自签名的,而是由中间证书签名的,而中间证书又由一些受信任的根授权机构签名——在这种情况下,我的服务配置非常相似,可以很好地接收它。第二种情况是使用自签名客户端证书进行 Azure 管理服务调用,但在这种情况下,我不知道服务器端是如何配置的。
因此我得出结论,证书的自签名性质使其成为 "not working"。我已经做了一些额外的事情 - 也许将一些东西添加到 web.config 或将证书添加到服务器端的某个证书存储中。我只是不知道这应该是什么。
如何使此设置生效?
IIS 尝试 "negotiate" 与客户端建立相互信任的连接,但由于客户端证书是自签名的,因此拒绝信任它。
您的选择:
- 使用知名证书颁发机构颁发的证书。这可行,但您必须每年左右重新颁发证书。
- 运行 您自己的 CA 基础设施,将其根 CA 证书添加到 "trusted root" 服务机器的证书存储中,并颁发用该根签名的证书(可能通过中间证书)。
- 将自签名证书添加到 "trusted root" 台服务机器中。 This may induce subtle yet serious security risks。我个人反对这个选项,因为它感觉很不安全。
- 切换到其他一些不使用客户端证书的身份验证方案。