.NETCore　HttpClientでオレオレ証明書で出るWinHttpExceptionを回避する

# 概要

こんなソースがMicrosoftの.NETのサイトで紹介されている。
.NETCoreでこれを動かそうとしたとき、オレオレ証明書で動いているhttpsのサイトを対象にした場合、Exceptionが発生する。
これを回避する。

```csharp
using System;
using System.Threading.Tasks;
using System.Net.Http;

public class AsyncSample
{
	static void Main()
	{
		GetURL().Wait();
	}

	private static async Task GetURL()
	{
		HttpClient client = new HttpClient();

		// This code executed asynchronously
		string response = 
			await client.GetStringAsync(
			"http://jsonplaceholder.typicode.com/posts/1");

		// This code executed after 
		// asynchronous code finalizes
		Console.WriteLine(response);
	}
}
```
[出典 : https://www.microsoft.com/net](https://www.microsoft.com/net)

# オレオレ証明書のときに出るエラー

**System.Net.Http.WinHttpException: セキュリティ エラーが発生しました**

```
sending the request. ---> System.Net.Http.WinHttpException: セキュリティ エラーが発生しました                                                                                                  
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)                                                                                                                
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)                                                                                           
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()                                                                                              
   at System.Net.Http.WinHttpHandler.<StartRequest>d__101.MoveNext()                                                                                                                           
   --- End of inner exception stack trace ---                                                                                                                                                  
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)                                                                                                                
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()                                                                                              
   at System.Net.Http.HttpClient.<FinishSendAsync>d__58.MoveNext()                                                                                                                             
--- End of stack trace from previous location where exception was thrown ---                                                                                                                   
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)                                                                                                                
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)                                                                                           
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()                                                                                              
   at System.Net.Http.HttpClient.<GetContentAsync>d__32`1.MoveNext()                                                                                                                           
--- End of stack trace from previous location where exception was thrown ---                                                                                                                   
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)                                                                                                                
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)                                                                                           
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()                                                                                                                                
   at SCBot.Program.<GetURL>d__0.MoveNext()                                                                                                                                                    
   --- End of inner exception stack trace ---                                                                                                                                                  
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)                                                                                                    
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)                                                                                         
   at System.Threading.Tasks.Task.Wait()                                                                                                                                                       
   at ******.Program.Main(String[] args)                 
```

# 対策

サーバ証明書のValidationチェックのCallback部分でtrueを返すようにする。

```csharp
using System;
using System.Threading.Tasks;
using System.Net.Http;

public class AsyncSample
{
	static void Main()
	{
		GetURL().Wait();
	}

	private static async Task GetURL()
	{
       
        // ---------------------これを足しておく------------------------------
        var httpClientHandler = new HttpClientHandler();
        // コメントで教えていただいた書き方
        httpClientHandler.ServerCertificateCustomValidationCallback = delegate { return true; };
        // delegateでかかない場合はこんな感じ
        // httpClientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, error) =>
        // {
        //   return true;
        // };
        // -----------------------------------------------------------------
        
		HttpClient client = new HttpClient(httpClientHandler);
		// This code executed asynchronously
		string response = 
			await client.GetStringAsync(
			"https://おれおれ証明書サイト/○○/△△");

		// This code executed after 
		// asynchronous code finalizes
		Console.WriteLine(response);
	}
}
```

# 参考にしたところ

- [HttpWebRequest/HttpClient with self-signed client certificate](https://github.com/dotnet/corefx/issues/8165)

- [Allowing Untrusted SSL Certificates with HttpClient](http://stackoverflow.com/questions/12553277/allowing-untrusted-ssl-certificates-with-httpclient)

- [HTTPS Cert Validation Callback in .Net Core](https://github.com/elastic/elasticsearch-net/issues/2198)