2013-03-04 160 views
21

我有一个ASP.NET Web API,我希望使用ssl。目前服务器正在使用自签名证书,并且此时都允许http和https。我有一个非常基本的测试客户端,可以正常使用http,但不适用于https。我想知道如何修改下面的客户端代码,以便它可以使用https。目前,IE,Firefox和Chrome都可以使用http和https(带有证书警告)连接到Web API,所以这使我相信我不应该修改服务器上的任何内容,只需在客户端代码中修改。这里的客户端代码:.NET客户端连接到ssl Web API

static void Main(string[] args) 
{ 
    try 
    { 
     if (args.Length != 1) 
     { 
      Console.WriteLine("Please provide a url, and only a url."); 
      return; 
     } 

     var url = new Uri(args[0]); 
     var urlAuthority = url.GetLeftPart(UriPartial.Authority); 
     var urlPathQuery = args[0].Substring(urlAuthority.Length); 
     HttpClient client = new HttpClient(); 
     client.BaseAddress = new Uri(urlAuthority); 
     HttpResponseMessage response = client.GetAsync(urlPathQuery).Result; 
     if (response.IsSuccessStatusCode) 
      Console.WriteLine(response.Content.ReadAsAsync<string>().Result); // expecting scalar results only 
     else 
      Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase); 
    } 
    catch (Exception ex) 
    { 
     Exception tempEx = ex; 
     while (tempEx != null) 
     { 
      Console.WriteLine(tempEx.Message); 
      tempEx = tempEx.InnerException; 
     } 
    } 
} 

当我运行上面的代码与我的http url,它工作正常。当我更改URL为https以下错误打印:

One or more errors occurred. 
An error occurred while sending the request. 
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. 
The remote certificate is invalid according to the validation procedure. 

我有一个问题是,如果客户端必须手动发送公钥给服务器,因此它知道如何发送回一个加密的响应,或者如果这在幕后自动发生?第二,现在在看到最后一个错误之后,我想知道如果我还需要在客户端执行其他操作来忽略证书警告,并且相信这个证书可以继续使用呢?

+0

您是否已将安全模式设置为在您的配置中传输? – Joe 2013-03-04 16:10:04

+0

另一个例子可以在这里找到:http://stackoverflow.com/a/42449178/112397 – TombMedia 2017-02-24 22:15:30

回答

38

看看C# Ignore certificate errors SO问题。我相信您可以使用ServicePointManager添加证书验证处理程序来规避证书验证。尽管在生产环境中使用签名证书可能是一个好主意。

ServicePointManager 
    .ServerCertificateValidationCallback += 
    (sender, cert, chain, sslPolicyErrors) => true; 
+1

我同意在prod中使用签名证书,但在这种情况下,我们的prod Web API将不会公开,因为它只与我们控制下的自动化客户端连接,但它仍然在互联网上,这就是为什么我们首先需要SSL。 – TTT 2013-03-04 17:05:57

+0

我有2点要求。1.此解决方案需要Dev和Prod环境之间的代码差异。我的意思是Prod不需要这个代码,它忽略了证书错误。 2.这是应用程序/语言特定的修复程序。如果jquery AJAX请求需要访问此API,该怎么办?在我看来,正如@Devin所说,通过推广到Root证书,自签名证书应该在开发机器上得到信任。使用IIS Express和SSL,请参阅此链接安装开发环境,无需警告http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx – 2016-06-16 20:06:21

3

此错误消息表示客户端在SSL握手期间不信任服务器证书。有些浏览器更宽容一些,并给你一个“红色栏”,但是从代码调用将导致401和被拒绝的呼叫。

您不需要对IIS中的客户端证书设置进行任何操作(因为我假设您没有使用客户端证书)。

此异常消息告诉您,在客户端进行验证时,自签名证书链会被拒绝。您可能要通过导出(无私钥),自签名证书并将其作为root证书安装在客户机上来解决此问题。

如果这不起作用,您需要创建一个新的CA(证书颁发机构证书),然后生成一个新的CA服务器证书。这个CA最终必须作为根证书安装在客户端机器上。

This is a good post显示使用makecert和pvk2pfx的过程。

编辑: It looks like there might be a way配置HttpClient忽略SSL错误。但是,我强烈建议您尽量不要从一开始就出现SSL错误。

+0

那么在客户端代码中没有什么可以告诉它允许它吗?没有证书作为root证书安装在客户端机器上,所有浏览器如何完成此操作? – TTT 2013-03-04 16:22:58

+0

@TTT所有客户端都安装了某些根证书。例如Verisign根证书。如果证书通过Verisign根证书签名(或在链中),则浏览器客户端信任该证书。这是SSL如何工作的核心。 – 2013-03-04 16:24:21

+0

我明白这一点。但是我尝试过的所有3个浏览器都可以使用SSL连接到相同的URL,但我的客户端不能。我想要做浏览器正在做的事情。如果未签名的证书在我的机器上不受信任,那么它对于浏览器也不信任,但浏览器仍然可以继续。 – TTT 2013-03-04 16:37:14

18

这对我有效。在对GetAsync的调用之前添加以下内容。

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

这会忽略SSL错误。这只能在不能伪造服务器身份的Intranet环境或其他封闭网络中推荐。