關於https雙向認證的知識可先行google,這時矸接代碼。git
爲了雙向認證,咱們首先得準備兩個crt證書,一個是client.crt,一個是server.crt,有時爲了驗證是否同一個根證書的驗證,這兩個證書能夠共有一個根證書root.crt。github
首先要生成這些證書,這裏採用了自簽證書方式:web
證書生成工具可在這裏下載(windows下生成):windows
安裝完成後在C:\OpenSSL-Win64\bin(最好不要改路徑,不然生成證書時要改配置文件路徑)下以管理員運行openssl.exe服務器
1、建立根證書asp.net
openssl genrsa -des3 -out root.key 工具
openssl req -new -key root.key -out root.csr ui
openssl x509 -req -days 3650 -sha1 -extensions v3_ca -signkey root.key -in root.csr -out root.crt google
分別在客戶端或服務端安裝根證書,windows上安裝證書時,證書存儲可選擇「受信任的根證書頒發機構」
2、建立服務端證書
openssl genrsa -des3 -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA root.crt -CAkey root.key -CAserial root.srl -CAcreateserial -in server.csr -out server.crt
openssl pkcs12 -export -in server.crt -inkey server.key -out server.pfx
3、建立客戶端證書
openssl genrsa -des3 -out client.key 2048
openssl req -new -key client.key -out client.csr
openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA root.crt -CAkey root.key -CAserial root.srl -CAcreateserial -in client.csr -out client.crt
openssl pkcs12 -export -in client.crt -inkey client.key -out client.pfx
接下來建立asp.net core web api項目,並把server.pfx添加到項目中,並設置屬性爲「始終複製」,接着修改Program.cs下的CreateWebHostBuilder方法就能夠:
1 public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 2 WebHost.CreateDefaultBuilder(args) 3 .UseKestrel(options => 4 { 5 options.Listen(IPAddress.Any, 80); 6 //啓用https,443端口 7 options.Listen(IPAddress.Any, 443, listenOptions => 8 { 9 var serverCertificate = new X509Certificate2("server.pfx", "ssssss"); 10 var httpsConnectionAdapterOptions = new HttpsConnectionAdapterOptions() 11 { 12 ClientCertificateMode = ClientCertificateMode.AllowCertificate, 13 SslProtocols = System.Security.Authentication.SslProtocols.Tls12, 14 //用chain.Build驗證客戶端證書 15 ClientCertificateValidation = (cer, chain, error) => 16 { 17 return chain.Build(cer); 18 }, 19 ServerCertificate = signingCertificate 20 }; 21 listenOptions.UseHttps(httpsConnectionAdapterOptions); 22 }); 23 }) 24 .UseStartup<Startup>();
爲了區分http和https請求,在HomeController中寫以下代碼:
1 [HttpGet] 2 public ActionResult<IEnumerable<string>> Get() 3 { 4 var cer = HttpContext.Connection.ClientCertificate; 5 //證書爲空,返回BadRequest 6 if (cer == null) 7 { 8 return BadRequest(); 9 } 10 else 11 { 12 return new string[] { "value1", "value2" }; 13 } 14 }
建立客戶應用,.net core的控制檯項目,把client.pfx添加到項目中,並設置屬性爲「始終複製」,而後代碼以下
1 static void Main(string[] args) 2 { 3 Console.WriteLine("enter start"); 4 while (true) 5 { 6 try 7 { 8 Console.WriteLine("一、Https 二、Http"); 9 switch (Console.ReadLine()) 10 { 11 case "1": 12 HttpsMethod(); 13 break; 14 case "2": 15 HttpMethod(); 16 break; 17 } 18 void HttpsMethod() 19 { 20 var handler = new HttpClientHandler(); 21 handler.ClientCertificateOptions = ClientCertificateOption.Manual; 22 handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls | SslProtocols.None | SslProtocols.Tls11; 23 try 24 { 25 //加載客戶端證書 26 var crt = new X509Certificate2(Directory.GetCurrentDirectory() + "/client.pfx", "cccccc"); 27 handler.ClientCertificates.Add(crt); 28 } 29 catch (Exception e) 30 { 31 Console.WriteLine(e.Message); 32 } 33 //用chain.Build驗證服務器證書 34 handler.ServerCertificateCustomValidationCallback = (message, cer, chain, errors) => 35 { 36 return chain.Build(cer); 37 }; 38 var client = new HttpClient(handler); 39 var url = "https://192.168.252.41 /api/values"; 40 var response = client.GetAsync(url).Result; 41 Console.WriteLine(response.IsSuccessStatusCode); 42 var back = response.Content.ReadAsStringAsync().Result; 43 Console.WriteLine(back); 44 } 45 void HttpMethod() 46 { 47 var client = new HttpClient(); 48 var url = "http://192.168.252.41/api/values"; 49 var response = client.GetAsync(url).Result; 50 Console.WriteLine(response.IsSuccessStatusCode); 51 var back = response.Content.ReadAsStringAsync().Result; 52 Console.WriteLine(back); 53 } 54 } 55 catch (Exception exc) 56 { 57 Console.WriteLine(exc.InnerException?.InnerException?.Message); 58 } 59 } 60 }
結果以下圖:
代碼:https://github.com/axzxs2001/Asp.NetCoreExperiment/tree/master/Asp.NetCoreExperiment/Certificate