从Windows服务中进行SSL连接时出现异常

时间:2012-01-10 08:42:51

标签: c# ssl windows-services

我正在开发简单的Windows服务,从远程Web服务发送和接收数据。 我决定使用WebClient类来实现它的简单性并增强它以在请求中包含证书,如下所示:

class MyWebClient : WebClient
{
    public X509Certificate cert { set; get; }
    protected override WebRequest GetWebRequest(Uri address)
    {
        HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(address);
        req.ClientCertificates.Clear();
        req.ClientCertificates.Add(cert);
        return req;
    }
}

这就是我准备和提出请求的方式:

try {
//...
string qry = "Some xml query...";
    System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object sender,
    X509Certificate certificate,
    X509Chain chain,
    SslPolicyErrors sslPolicyErrors) { return true; };

X509Certificate cert = X509Certificate.CreateFromCertFile(appPath + @"\data\cert.der");
MyWebClient cl = new MyWebClient();
cl.cert = cert;
string xmlReq = qry; 
cl.Headers[HttpRequestHeader.ContentType] = "text/xml";
var data = Encoding.UTF8.GetBytes(xmlReq);
byte[] res = cl.UploadData(apiUrl, data);
cl.Dispose();

string result = Encoding.UTF8.GetString(res);
} catch (Exception ex) {
//...
}
//...

现在,我知道从文件加载证书不是最好的主意,但这不是重点。关键是上面的代码在桌面应用程序中完美运行,但在Windows服务中抛出“无法为SSL / TLS建立安全通道”异常。 我尝试在“localService”和“networkService”帐户下安装该服务,但没有任何不同。

更新:在“用户”下安装也没有帮助。 我错过了什么吗?

1 个答案:

答案 0 :(得分:2)

使用以下方法加载证书时:

X509Certificate cert = X509Certificate.CreateFromCertFile(appPath + @"\data\cert.der");

您只是加载证书。但是,要使客户端证书身份验证起作用,您需要也提供私钥(否则,任何人都可以使用任何证书)。

在聊天室讨论之后,您已经表明您还有.p12(PKCS#12),.key.pem文件,以及{{ 1}}你试图加载的文件。 通常,这些扩展名以这种方式使用:

  • .der用于DER编码(二进制)中的证书本身。
  • .der用于PEM编码中的证书本身(DER的base64编码,.pem分隔符内)。
  • 私钥的
  • ---BEGIN....--- ... --- END ---
  • .key(或.p12)用于PKCS#12文件,该文件将包含证书(可能还包含CA链)和私钥。

在.Net中,基础.pfx将不允许您加载私钥和证书。您应该考虑将p12文件加载到X509Certificate2实例中:它本质上是一个便利类,它不仅可以为证书建模,还可以将私钥与对象关联。

我不确定为什么它可以用作桌面应用程序而不是服务。我的猜测是,它会在其中一种情况下自动从用户或机器商店中获取一个cert +私钥。无论哪种方式,您的桌面应用程序都无法使用DER文件进行身份验证。