使用证书身份验证访问 Web 服务和 HTTP 接口

Posted

技术标签:

【中文标题】使用证书身份验证访问 Web 服务和 HTTP 接口【英文标题】:Accessing a web service and a HTTP interface using certificate authentication 【发布时间】:2012-06-24 14:46:36 【问题描述】:

这是我第一次使用证书认证。 一个商业伙伴公开了两个服务,一个 XML Web 服务和一个 HTTP 服务。我必须使用 .NET 客户端访问它们。

我的尝试

0。设置环境

我已经使用 certmgr.exe 在我的本地计算机(win 7 专业版)中安装了 SSLCACertificates(在 root 和两个中间)和客户端证书。

1.对于网络服务

我有客户端证书 (der)。 服务将通过 .NET 代理使用。

代码如下:

OrderWSService proxy = new OrderWSService();
string CertFile = "ClientCert_DER.cer";

proxy.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(CertFile));
orderTrackingTO ot = new orderTrackingTO()  order_id = "80", tracking_id = "82", status = stateOrderType.IN_PREPARATION ;
resultResponseTO res = proxy.insertOrderTracking(ot);

最后一条语句报告了异常:The request failed with an empty response

2。对于 HTTP 接口

这是一个HTTPS接口,我必须通过POST方法调用。 HTTPS 请求将使用 HTTPWebRequest 从 .NET 客户端发送。

代码如下:

string PostData = "MyPostData";

//setting the request
HttpWebRequest req;
req = (HttpWebRequest)HttpWebRequest.Create(url);
req.UserAgent = "MyUserAgent";
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(CertFile, "MyPassword")); 

//setting the request content
byte[] byteArray = Encoding.UTF8.GetBytes(PostData);
Stream dataStream = req.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();

//obtaining the response
WebResponse res = req.GetResponse();
r = new StreamReader(res.GetResponseStream());

最后一条语句报告了异常:The request was aborted: Could not create SSL/TLS secure channel

3.最后尝试:使用浏览器

在 Chrome 中,安装证书后,如果我尝试访问两个 url,我会收到 107 错误:

Error 107 (net::ERR_SSL_PROTOCOL_ERROR)

我被卡住了。

【问题讨论】:

您无法使用 ssl 证书授权发出 http 请求。它需要通过https完成。你需要这个证书吗?如果答案是肯定的,那么您必须使此 Web 服务通过 https 进行通信。 @harry180。感谢澄清。我编辑了问题。 在 http 协议中,当您发送用户名和密码时,必须至少在 MD5 中加密。即使您这样做,也很容易将此信息泄露给未经授权的人。重新考虑使用 https 协议进行这种信息共享。 【参考方案1】:

以下内容应该可以帮助您识别问题,这里有两种测试 SSL 连接的方法,一种是测试站点,另一种是回调方法,以确定 SSL 失败的原因。如果不出意外,它应该能让您更好地了解它失败的原因。

调用该方法时,会弹出选择证书对话框,显然,当您真正执行此操作时,您会希望自动从证书存储中读取。我之所以把它放进去是因为如果没有找到有效的证书,那么你就会知道你的问题出在证书的安装方式上。

最好的办法是将此代码放在一个简单的控制台应用程序中:

using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Net;

private static void CheckSite(string url, string method)

    X509Certificate2 cert = null;
    ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;

    X509Store store = new X509Store(StoreLocation.LocalMachine);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
    X509Certificate2Collection certcollection = (X509Certificate2Collection)store.Certificates;
    // pick a certificate from the store
    cert = X509Certificate2UI.SelectFromCollection(certcollection, 
            "Caption",
            "Message", X509SelectionFlag.SingleSelection)[0];

    store.Close();

    HttpWebRequest ws = (HttpWebRequest)WebRequest.Create(url);
    ws.Credentials = CredentialCache.DefaultCredentials;
    ws.Method = method;
    if (cert != null)
        ws.ClientCertificates.Add(cert);

    using (HttpWebResponse webResponse = (HttpWebResponse)ws.GetResponse())
    
        using (Stream responseStream = webResponse.GetResponseStream())
        
            using (StreamReader responseStreamReader = new StreamReader(responseStream, true))
            
                string response = responseStreamReader.ReadToEnd();
                Console.WriteLine(response);
                responseStreamReader.Close();
            

            responseStream.Close();
        
        webResponse.Close();
    


/// <summary>
/// Certificate validation callback.
/// </summary>
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)

    // If the certificate is a valid, signed certificate, return true.
    if (error == System.Net.Security.SslPolicyErrors.None)
    
        return true;
    

    Console.WriteLine("X509Certificate [0] Policy Error: '1'",
        cert.Subject,
        error.ToString());

    return false;

【讨论】:

非常感谢。我试试看。

以上是关于使用证书身份验证访问 Web 服务和 HTTP 接口的主要内容,如果未能解决你的问题,请参考以下文章

WCF与相互身份验证

利用CA证书配置安全Web站点

我用WEB界面可以访问SVN服务器,但是显示是证书有问题,但是用客户端就完全访问不了,是啥问题

与 Web 服务的相互身份验证

如何设置IIS以验证客户端证书并将其作为http标头传递给后端?

使用 https 使用不同的 web 服务但只有一个使用证书身份验证后的 Axis2 问题