前几天搞go 的Grpc和http2的双向认证。现在来搞搞。net core 里面是如何实现的
首先需要下载 OpenSSL http://slproweb.com/products/Win32OpenSSL.html
导出证书 或者生成【我后面有生成的方法, 但是在我win7上 安装证书后有些问题,所以可以导出】
运行-> certmgr.msc 如图:我这里有2个 一个 作为作为server2.pfx"一个作为client2.pfx
创建项目
接下来创建asp.net core web api项目,并把server.pfx添加到项目中,并设置属性为“始终复制”,接着修改Program.cs下的CreateHostBuilder方法就可以:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseKestrel( options => { options.Listen(IPAddress.Any, 5001, listenOptions => { var serverPath = AppDomain.CurrentDomain.BaseDirectory + "cert\\server2.pfx"; var serverCertificate = new X509Certificate2(serverPath, "123456789"); var httpsConnectionAdapterOptions = new HttpsConnectionAdapterOptions() { ClientCertificateMode = ClientCertificateMode.AllowCertificate, SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls | SslProtocols.None | SslProtocols.Tls11, ClientCertificateValidation = (cer, chain, error) => { return chain.Build(cer); }, ServerCertificate = serverCertificate }; listenOptions.UseHttps(httpsConnectionAdapterOptions); }); }).UseStartup<Startup>(); });
为了区分http和https请求,在WeatherForecastController中写如下代码:
[HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); var cer = HttpContext.Connection.ClientCertificate; //证书为空,返回过去的时间 if (cer == null) { return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(-index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); }
创建客户应用,.net core的控制台项目,把client.pfx添加到项目中,并设置属性为“始终复制”,然后代码如下
static void Main(string[] args) { HttpsMethod(); } static void HttpsMethod() { ServicePointManager.ServerCertificateValidationCallback = delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }; var handler = new HttpClientHandler(); handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls | SslProtocols.None | SslProtocols.Tls11; try { //加载客户端证书 var crt = new X509Certificate2(Directory.GetCurrentDirectory() + "/cert/client2.pfx", "123456789"); handler.ClientCertificates.Add(crt); } catch (Exception e) { Console.WriteLine(e.Message); } //用chain.Build验证服务器证书 handler.ServerCertificateCustomValidationCallback = (message, cer, chain, errors) => { return chain.Build(cer); }; var client = new HttpClient(handler); var url = "https://localhost:5001/WeatherForecast"; var response = client.GetAsync(url).Result; Console.WriteLine(response.IsSuccessStatusCode); var back = response.Content.ReadAsStringAsync().Result; Console.WriteLine(back); }
结果如下图:
关于证书的创建, 我参考了别人做法, 但还是提示 the remote certificate is invalid according to the validation procedure., 网上说的 dotnet dev-certs https --trust 试了没用, 还有就是安装证书 也还是没用
证书创建:
一、创建根证书
//生成key文件,输入密码: openssl genrsa -des3 -out root.key //生成请求证书文件,如果安装路径发生改变,可以通过在下面命令后面添加-config openssl.cfg来指明配置文件路径 openssl req -new -key root.key -out root.csr //生成一个10年期根证书 root.crt: openssl x509 -req -days 3650 -sha1 -extensions v3_ca -signkey root.key -in root.csr -out root.crt //分别在客户端或服务端安装根证书,windows上安装证书时,证书存储可选择“受信任的根证书颁发机构
二、创建服务端证书
//生成key文件,输入密码 openssl genrsa -des3 -out server.key 2048 //生成请求证书文件,如果安装路径发生改变 openssl req -new -key server.key -out server.csr //用根证书生成一个10年期证书 server.crt: 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 //生成.net core识别的证书文件server.pfx openssl pkcs12 -export -in server.crt -inkey server.key -out server.pfx
三、创建客户端证书
//生成key文件,输入密码 openssl genrsa -des3 -out client.key 2048 //生成请求证书文件,如果安装路径发生改变 openssl req -new -key client.key -out client.csr //用根证书生成一个10年期证书 client.crt: 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 //生成.net core识别的证书文件client.pfx openssl pkcs12 -export -in client.crt -inkey client.key -out client.pfx
这个操作方法 不确定是否好用, 网上别人成功了的, 但是我安装后如图:
参考: