在IIS 6上使用ASP.NET MVC站点的客户端证书
想要通过客户端证书实现身份验证,我遇到了一些问题。
首先是一些事实
整个站点都使用SSL。我正在使用IIS 6(在Windows Server 2003上),并且已将站点配置为接受客户端证书,而不要求它们。但是,大多数浏览器都以某种方式实现,以便仅在严格要求时才要求用户提供证书。因此,身份验证模型并不是真正有用的。
我自己的建议
我的第一个想法是设置HttpResponse.Status属性,但它要求第一个空格之前的字符为整数。获取浏览器发送客户端证书的有用状态是"需要403.7客户端证书",因此它将不起作用(除非我们可以覆盖它)。
我还以为我只是将IIS配置为要求特定路径的客户端证书,但是这种解决方案仅适用于物理文件,而不适用于路由。
一种可能的解决方案是制作一个特定的文件夹并为其要求客户端证书,这比解决方案更像是骇客。因此,如果有人有更好的建议,我想避免这种情况。
澄清说明
我已经测试了Internet Explorer,Firefox和Chrome的浏览器响应(我将Chrome作为主要浏览器,将Firefox作为辅助浏览器)。除非我在IIS中按要求配置,否则所有浏览器都不会请求客户端证书。
HTTP状态代码403.7是由于我的理解所允许的,因为RFC 2616仅将状态代码定义为前三位。当需要客户端证书时,由于IIS 6返回403.7,我认为发送该证书将迫使IIS进入触发要求的特殊模式。
我想现在的问题是如何配置IIS,以便在给定虚拟路径而非物理路径的情况下要求证书。
解决方案
当仅请求而不是要求证书时,服务器发送的CertificateRequest消息没有什么不同。在这两种情况下,服务器都发出相同的请求,并且当客户端未能提供所需的证书时,服务器将简单地终止握手。因此,如果浏览器似乎忽略了"请求",那么它也应该看上去也忽略了"要求"。
检查以下内容:
- 浏览器是否配置为忽略所有证书请求,而不发送任何证书请求?
- 浏览器是否配置为使用给定证书而不提示用户? (换句话说,我们怎么知道浏览器没有发送证书?)
- 服务器实际上是在请求证书吗?
我测试这最后一种情况的方法是使用OpenSSL(在Cygwin中也可用)工具:
openssl s_client -connect server.y.com:443 -msg
服务器发送其证书消息后,它将插入一个CertificateRequest方法,如果它不请求客户端身份验证,则该方法不存在。 s_client输出看起来像这样:
<<< TLS 1.0 Handshake [length 0008], CertificateRequest 0d 00 00 04 01 01 00 00
如果服务器仅在特定路径上使用客户端身份验证,我不确定它是如何工作的,因为在客户端传输HTTP请求之前,初始的SSL握手已完成。此时服务器请求新的握手是合理的,但我从未测试过看有哪些服务器支持此握手。
我们可以手动通过s_client伪造HTTP请求,输入:
GET /your/path/here HTTP/1.1[Enter] Host: server.y.com:443[Enter] [Enter]
如果我们根本看不到CertificateRequest消息,则说明服务器设置不正确。
基于目录结构指定安全性约束非常普遍,实际上可以很好地简化安全性管理。如果这可以为我们提供解决方案,请不要为此感到难过。
403.7不是HTTP状态代码。这是微软的"拥抱,扩展和扑灭"手段吗?无论如何,这听起来都不是正确的方向,因为这是传输层问题,而不是应用程序层问题。