[C#]用HttpWebRequest加载证书建立SSL通道时发生异常的解决办法


编写者:郑昀@UltraPower


关键字:HttpWebRequest,

SSL,X509Certificate


dotNet  Framwork 1.1


编写时间:2005-3-29


WSE 2.0 SP3

 

目的:

对于用HttpWebRequest加载证书请求远端https服务器时,发生的

“基础连接已经关闭: 无法与远程服务器建立信任关系。”/

“The underlying connection was closed. Could not establish a secure SSL/TLS connection”错误,我们可以用如下方式解决。

重现:

使用以下代码,你就可以得到这个错误“基础连接已经关闭: 无法与远程服务器建立信任关系”:


using System;

using System.Text;

using System.Net;

using System.IO;

using System.Security.Cryptography.X509Certificates;

 

using Microsoft.Web.Services2.Security;

using Microsoft.Web.Services2.Security.Tokens;

using Microsoft.Web.Services2.Security.X509;

 

static void Main(string[] args)

        {

            StringBuilder sb=new StringBuilder();

            string _strToRequest = "send";

 

            try

            {

                //POST请求开始

                byte[] bt=Encoding.Default.GetBytes("send");

                HttpWebRequest Req=(HttpWebRequest)System.Net.WebRequest.Create("https://202.108.CCC.XXX:Port//");

                Req.KeepAlive=true;

                //Req.Timeout=60000;

                Req.ContentType="text/xml";

                Req.ContentLength=_strToRequest.Length;

                Req.Method="POST";

                X509CertificateStore store = X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore );

                store.OpenRead();

    

                //读取证书的keyid

                Microsoft.Web.Services2.Security.X509.X509CertificateCollection certs =

                    store.FindCertificateByKeyIdentifier( Convert.FromBase64String( "CXv+xZ78zI3qWHGJ6Wh9BF6B23A=" ) );

                X509SecurityToken token = null;

                if (certs.Count > 0)

                {

                    // 得到证书存储区的第1个人证书

                    token = new X509SecurityToken( ((Microsoft.Web.Services2.Security.X509.X509Certificate) certs[0]) );

                } 

                if(token != null)

                    Req.ClientCertificates.Add(token.Certificate);

                Req.KeepAlive=true;

 

                Stream ReqStream=Req.GetRequestStream();

                ReqStream.Write(bt,0,bt.Length);

                ReqStream.Close();

                //得到响应

                HttpWebResponse res=(HttpWebResponse)Req.GetResponse();

                StreamReader sr=newStreamReader(res.GetResponseStream(),Encoding.Default);

                sb.Append(sr.ReadToEnd());

                res.Close();

                sr.Close();

            }

            catch(Exception ex)

            {    

                sb.Remove(0,sb.Length);

                sb.Append("<?xml version=\"1.0\" encoding=\"gb2312\"?>\n");

                sb.Append("<slia ver=\"1.0.0\">\n");

                sb.Append("<result resid=\"501\">"+ex.Message+"</result>\n");

                sb.Append("</slia>\n");

            }

 

            Console.WriteLine(sb.ToString());

 

            Console.Read();

        }

原因:

在“http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconhostingremoteobjectsininternetinformationservicesiis.asp”提到:

证书标识特定的计算机,该计算机的名称位于证书的公共名称中。但是,很容易就会更改计算机的名称或使用客户端配置文件中的“localhost”,这会在客户端和服务器证书中的公共名称之间造成不匹配的情况。在 .NET Framework 1.0 版中,这一不匹配的情况将被忽略,并且将在服务器上引发调用。

从 .NET Framework 1.1 版开始,这一不匹配的情况会引发以下异常:“System.Net.WebException:基础连接已经关闭:无法与远程服务器建立信任关系”。如果您无法配置远程处理客户端以使用证书公共名称,则可以使用客户端应用程序配置文件中的以下设置重写这一不匹配的情况。

<system.net>

   <settings>

      <servicePointManager

         checkCertificateName="true"

      />

   </settings>

</system.net>

若要以编程方式使客户端忽略证书名称不匹配,客户端必须创建一个特定类的实例,如果 certificateProblem值为 0x800c010f,该类将实现 ICertificatePolicy 接口并实现 CheckValidationResult 方法以返回true。然后,您必须将该对象注册到 System.Net.ServicePointManager 对象,方法是将该对象传递到ServicePointManager.CertificatePolicy 属性。”

解决之道:

但是用它列出的代码还是不对,我们改为CheckValidationResult无条件返回true即可。如下所示声明一个TrustAllCertificatePolicy类:

 


public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy

        {

            public TrustAllCertificatePolicy()

            {}

 

            public bool CheckValidationResult(ServicePoint sp,

                System.Security.Cryptography.X509Certificates.X509Certificate cert,

                WebRequest req, int problem)

            {

                return true;

            }

        }

然后,在请求之前加上

System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

即可。

这样,代码就可以顺利和https服务器建立SSL通道了。

编写者:郑昀@UltraPower

时间: 2024-06-12 20:55:43

[C#]用HttpWebRequest加载证书建立SSL通道时发生异常的解决办法的相关文章

windows 2008 服务器 x509certificate2加载证书 出现了内部错误

问题描述 windows2008服务器x509certificate2加载证书出现了内部错误,同样的代码在windows2003服务器是没有问题的.请大侠们指教 解决方案 解决方案二:问题补充,非常急解决方案三:问题解决了吗?我也有同样的问题!解决方案四: 解决方案五:iis找到部署的站点应用连接池,右键高级设置,找到"加载用户配置文件"改为true.windowservice2008默认为false的.我也遇到这种问题不过用了这个办法完美解决了

jqgrid的subgrid能不能一开始就加载而不是等到展开时再加载?

问题描述 jqgrid的subgrid能不能一开始就加载而不是等到展开时再加载? 基本上网上的例子都是把subgrid的创建代码卸载subGridRowExpanded方法里,不知道有没有方法实现父表加载数据的时候能自动把subgrid一起加载进来? 解决方案 subGridOptions:{expandOnLoad: true} jqGrid subGrid配置

System.BadImageFormatException: 试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)

原文 System.BadImageFormatException: 试图加载格式不正确的程序. (异常来自 HRESULT:0x8007000B) 用C#调用DLL文件,运行后报错如下: System.BadImageFormatException: 试图加载格式不正确的程序. (异常来自 HRESULT:0x8007000B) 项目右键属性->项目设计器->生成->平台->把'默认设置(任何 CPU)'改为x86.因为'任何 CPU'的程序在64位的机器上就会用运行为64位,而

Android Studio NDK开发同时加载多个SO文件时该如何配置

问题描述 Android Studio NDK开发同时加载多个SO文件时该如何配置 使用AS学习NDK开发时,当DEMO中只用到一个SO文件,开发.调试均正常. AS在开发NDK时是不需要手动编写Android.mk和Application.mk的,而通过配置build.gradle文件,可以自动在build目录下生成Android.mk,但是在配置build.gradle文件时,发现在ndk{...}中,只能配置一个moduleName,而这个moduleName正是编译后生成的SO文件名,请

installutillwindows服务,提示在初始化安装时发生异常:System.BadImageFormatException: 未能加载文件或程序集“”

问题描述 在初始化安装时发生异常:System.BadImageFormatException:未能加载文件或程序集""或它的某一个依赖项.生成此程序集的运行时比当前加载的运行时新,无法加载此程序集..在线等大神帮我调试 解决方案 解决方案二:如图所示,我已经奔溃,昨天安装都没问题,就应该不是框架版本问题,今天出异常解决方案三:通常是生成程序选择的平台的问题.试试anycpu和x86解决方案四:楼主解决了吗?求方法,解决方案五:楼主解决了吗?求方法,解决方案六:出现这个错误是因为你的程

HttpWebRequest使用注意(发生阻塞的解决办法)

原文 http://www.cnblogs.com/Fooo/archive/2008/10/31/1323400.html HttpWebRequest使用注意(发生阻塞的解决办法)   HttpWebRequest myRequest = null;            HttpWebResponse myResponse = null;            Stream reqStream = null;             Stream resStream = null;    

禁用工行加载后打开IE9总是弹出提示的解决方法

为了不影响IE浏览器打开的速度,一般情况我们会把一些不经常用的IE加载项给禁用了,等到需要的时候在启动.但是如果你安装了工商银行网上银行加载项,那么你就悲剧了. 该加载项启动占用时间太长就算了,想着那就暂时先禁用他吧.然后打开"工具"-> "管理加载项",在里面找到 ICBC Anti-Phishing class 加载项将其禁用,以为至此就OK了. 无奈以后每次启动IE9的时候,他都会弹出"ICBC Anti-Phishing class"

Windows系统中出现无法加载这个硬件的设备驱动程序(代码39)的解决方法介绍

近日不知何故,光驱和虚拟光驱盘符都不见了,查看系统发现硬件前面有黄色感叹号,无法使用,在网上搜索,发现有很多人出现同样的问题,只是解决的方法都不对,找了两天,终于找到了解决的方法: 修复"光驱图标不见"记 电脑没用几天,突然发现光驱图标不见了,系统提示为:Windows 无法加载这个硬件的设备驱动程序.驱动程序可能已损坏或不见了. (代码 39) 1.       我卸载了光驱,结果是能识别,但提示安装出错,错误还是一样: 2.       我把金山模拟光驱卸载,结果还是一样: 3. 

webview加载-如何提高webview缓存效率,或者怎么解决缓存问题??

问题描述 如何提高webview缓存效率,或者怎么解决缓存问题?? 如何提高webview缓存效率,或者怎么解决缓存问题??或者有什么技巧能够让缓存看上去不会那么长!!!不然白屏期太长了!!! 解决方案 有关webview缓存问题WebView使用缓存的问题Android WebView的缓存 解决方案二: 页面本身加载太慢了.可以先后台加载然后再显示