SSL 对等验证
使用 CA 文件在客户端验证服务器证书
引言
当使用 HTTPS 和 SSL 调用 Web 服务时,主机验证和对等验证需要处理以保证安全。本文展示并解释了当通过SSL保护的HTTPS调用 Web 服务时,如何成功地进行对等验证。
Using the Code
大多数 Web 服务托管在 HTTPS 上,并由 SSL 保护,因此其他人无法使用它。很多时候,当我们浏览一个 HTTPS 站点时,我们会收到一个证书对话框,要求我们信任该提供者。这是 Web 服务器发送的服务器证书。我们接受证书并继续前进。在桌面应用程序中,当我们执行类似的任务(例如访问使用 HTTPS 和 SSL 的 Web 服务)时,我们无法收到任何对话框来信任证书,问题就来了。
通过创建我们自己的实现 ICertificatePolicy
接口的 CertificatePolicy
类,可以轻松实现这一点。例如,这样的类可以写成
public class MyPolicy : ICertificatePolicy {
public MyPolicy() {
}
public bool CheckValidationResult(ServicePoint srvPoint,
X509Certificate certificate,
WebRequest request, int certificateProblem)
{
// Perform operations to verify
// the certificate and return true or false
return true;
}
}
并且可以设置
ServerCertificateValidationonCallback = MyPolicy();
上面的代码也可以使用 System.Net.ServicePointManager.ServerCertificateValidationonCallback
的委托来编写。
System.Net.
ServicePointManager.ServerCertificateValidationCallback = {
(Object sender, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors) {
return true;
}
};
上面的代码接受服务器证书(在浏览器上弹出的信任提供者的对话框)。它隐式地返回 true
,这意味着它接受任何服务器证书并继续访问 Web 服务。
这非常简单容易。但是,如果 SSL 专门用于安全和密码学,并且可以如此容易地绕过,那么 SSL 还有什么意义呢?什么都没有,对吧?
当我们的客户端对照任何证书文件验证此服务器证书时,即,没有验证验证证书来验证服务器证书,客户端无法访问来自提供者的任何 Web 服务。这就像提供密码或验证密码一样。如果没有实际验证,给出和接收数据的 Web 服务应该很容易伪造。因此,我们需要使用“正确”版本的验证证书 *来验证服务器证书。验证证书只是一个 CA 文件,它比较服务器证书的数据。如果两者匹配,则返回 true
并允许我们访问 Web 服务,否则返回 false
并且不允许我们访问 Web 服务及其机密数据。
注意*:用于验证的证书与客户端证书不同,两者不同,它们的角色也不同。如果服务器需要客户端证书,则将客户端证书传递给服务器。可以使用 request.ClientCertificates
属性进行设置。
现在重点来了:我们如何验证服务器证书是否正确,或者服务器证书是否与验证证书匹配?虚假用户可以更改服务器证书或用于验证的证书,因此我们必须注意双方。
以下代码可帮助您接受服务器证书,并根据 CA 文件验证证书。
记住:接受服务器证书的代码应该只在整个应用程序生命周期中设置一次。并且每当发出请求时都会自动调用它。因此,为了便于编码,我们将把 SSL 证书部分与请求部分分开。
以下是设置和处理 SSL 证书部分的代码
// Certificate to verify
private X509Certificate2 verifyCert = null;
private void setSSLCertificate() {
veriftCert = new X509Certificate2("ca_verify.crt");
ServicePointManager.ServerCertificateValidationCallback += new
System.Net.Security.RemoteCertificateValidationCallback(
customCertificateValidation);
}
public bool customCertificateValidation(Object sender,
X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
switch(sslPolicyErrors) {
case RemoteCertificateChainErrors:
case RemoteCertificateNameMismatch:
case RemoteCertificateNotAvailable:
break;
}
// With this we have accepted the server certificate
// Now, VERIFY the certificate against verifyCert
// If details of both the certificates matches, then returns true, else false
return verifyCert.Verify();
}
就这样。这就是处理对等验证的方式,并且应该注意,不要进行任何硬编码或在代码中进行比较。
现在,每当执行任何请求时,将首先调用 customCertificateValidation()
,如果该函数返回 true
,则请求将能够继续,否则将捕获 WebException
。
private void SendPost(String post_data) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
<a href="https://ae-q01.com/">https://ae-q01.com/</a>);
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
byte[] postBytes = Encoding.ASCII.GetBytes(psot_data);
Stream requestStream = null;
try {
// Send
request.ContentLength = postBytes.Length;
requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
} catch (WebException we) {
// If our customCertificateValidation returns false, here it will be caught.
// You can check the status of WebException we.Status,
// mostly it returns TrustFailure and handle them
} catch(Exception e) {
// Handle other normal request errors
} finally {
if (requestStream != null)
requestStream.Close();
}
}
不要忘记在应用程序启动时或在调用任何 Web 服务之前适当的时间调用 setSSLCertificate()
。
这就是 SSL 对等验证的全部内容。我确信这肯定会帮助更多的开发人员实际交叉检查 SSL 验证,而不仅仅是盲目地接受服务器证书。
请告诉我它是否有效。
关注点
我想执行 SSL 对等验证。我在 Google 上搜索并在论坛中问了很多问题,但只能找到如何接受服务器证书,而不是如何验证它,这在您访问实现 SSL 安全性的 Web 服务时是最重要的。最后,当我找到解决方案时,我想与所有人分享,以使其他人的工作更容易一些。
历史
这是我在 CodeProject 上的第一篇文章。如果我犯了任何错误,请告知我; 欢迎任何改进建议。