最近有個項目要調用客戶用java寫的帶https的webservice,對方提供了證書文件 test.pfx,我這里調用方式如下:
//webservice代理類 SvcService svc = new SvcService(); //證書文件路徑 string filePath = ConfigurationManager.AppSettings["pfxUrl"]; X509Certificate cert = new System.Security.Cryptography.X509Certificates.X509Certificate(filePath, "123456"); //將證書添加客戶端證書集合 svc.ClientCertificates.Add(cert); //webservice調用代碼...
測試調用報錯:請求被中止: 未能創建 SSL/TLS 安全通道,於是趕緊google,找到如下解決方案:
在webservice代理類的構造函數中添加下面的代碼,繞過服務器證書驗證。
public static bool CheckValidationResult(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; } public SvcService() { ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); this.Url = ConfigurationManager.AppSettings["host"]; }
本地vs環境下再試,好了!調用成功!不報錯了!於是趕緊發布到IIS服務器上試一下,郁悶的是服務器上居然報錯,還是這個未能創建 SSL/TLS 安全通道!
於是繼續google,找到下面的解決方法:
1.將客戶端證書文件導入到本地計算機賬戶下的個人存儲區。
2.下載winhttpcertcfg.exe 這個工具,下載地址:http://www.microsoft.com/en-us/download/details.aspx?id=19801
3.安裝后一般是在C:\Program Files\Windows Resource Kits\Tools這個路徑下面。 進入cmd 執行如下命令:winhttpcertcfg -g -c LOCAL_MACHINE\MY -s "test" -a "NetworkService"
這里解釋一下這幾個參數的含義:
-g 是grant授權的意思,將該證書的使用權限授予某個用戶
-c 是certstore證書存儲區,指定 本地計算機/當前用戶下的證書存儲區位置,我們這里是MY,個人存儲區
-s 是subjectstr 用於模糊匹配證書的一個字符串,我們這里用證書文件名 test
-a 是account要授權的用戶帳號
這里要注意的是授權賬戶,IIS6下面一般用的是NetworkService,如果你用的IIS7,必須要保證你網站所用的應用程序池的 "標識"和要授權的賬戶一致。
執行成功之后,會列出模糊匹配出的證書列表和已經授權的賬戶。
然后程序代碼做如下更改:
//webservice客戶端代理類 SvcService svc = new SvcService(); //打開本地計算機下的個人證書存儲區 X509Store certStore = new System.Security.Cryptography.X509Certificates.X509Store(StoreName.My, StoreLocation.LocalMachine); certStore.Open(OpenFlags.ReadOnly); //根據名稱查找匹配的證書集合,這里注意最后一個參數,傳true的話會找不到 X509Certificate2Collection certCollection = certStore.Certificates.Find(System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName, "test", false); //將證書添加至客戶端證書集合 svc.ClientCertificates.Add(certCollection[0]); //webservice調用代碼
再測試了一下,調用正常!至此這個問題算圓滿解決了!
總結:我們導入的客戶端證書並不是所有的賬戶都能訪問和使用,因為我們的開發服務器也就是VS自帶的服務器默認使用當前用戶,而當前用戶具有使用證書的權限,所以我們在本地調試的時候,一切正常。當我們將網站部署到IIS后,由於IIS的使用的是內置賬戶不具有證書的使用權限,所以就出現了上述問題,這個時候我們只需用winhttpcertcfg這個工具給指定賬戶授予使用證書的權限,就可以正常調用啦!