zoukankan      html  css  js  c++  java
  • asp.net 5.0 https的双向认证(windows和ubuntu)以及go的调用

    前几天搞go 的Grpc和http2的双向认证。现在来搞搞。net core 里面是如何实现的

    首先需要下载 OpenSSL http://slproweb.com/products/Win32OpenSSL.html 

    windows

    证书创建:

    一、创建根证书

    //生成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

    创建项目

    接下来创建asp.net core web api项目,并把server.pfx添加到项目中,并设置属性为“始终复制”,接着修改Program.cs下的CreateHostBuilder方法就可以: linux 上路径变为 "cert/server.pfx“

     public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
    
                        webBuilder.ConfigureKestrel(kerstrel =>
                        {
                            kerstrel.ConfigureHttpsDefaults(https =>
                            {
                                var serverPath = AppDomain.CurrentDomain.BaseDirectory + "cert\server.pfx";
                                var serverCertificate = new X509Certificate2(serverPath, "123456789");
                                https.ServerCertificate = serverCertificate;
                                https.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
                                https.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls | SslProtocols.None | SslProtocols.Tls11;
                                https.ClientCertificateValidation = (cer, chain, error) =>
                                           {
                                               return chain.Build(cer);
                                           };
    
                            });
                        });
                    });

    为了区分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)
            {
                var handler = new HttpClientHandler()
                {
                    SslProtocols = SslProtocols.Tls12,
                    ClientCertificateOptions = ClientCertificateOption.Manual,
                    ServerCertificateCustomValidationCallback = (message, cer, chain, errors) =>
                    {
                        return chain.Build(cer);
                    }
                };
                var path = AppDomain.CurrentDomain.BaseDirectory + "cert\client.pfx";
                var crt = new X509Certificate2(path, "123456789");
                handler.ClientCertificates.Add(crt);
    
                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);
            }

    结果如下图:

    Linux(Ubuntu环境安装)

    //参考 https://docs.microsoft.com/zh-cn/dotnet/core/install/linux-ubuntu
    
    sudo apt update //
    wget https://packages.microsoft.com/config/ubuntu/20.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
    sudo dpkg -i packages-microsoft-prod.deb
    
    sudo apt-get update; 
      sudo apt-get install -y apt-transport-https && 
      sudo apt-get update && 
      sudo apt-get install -y dotnet-sdk-5.0

    安装证书:

    //Ubuntu上CA证书的配置可以通过工具ca-certificates来方便的进行。该工具默认是随Ubuntu安装的,如果没有可以通过下面的命令来安装:
    sudo apt-get install ca-certificates
    //需要安装CA证书我们只需要将其放在”/usr/share/ca-certificates”目录或其子目录下,ca-certificates工具就能自动扫描到。为了不与其它根证书混淆,我们创建一个子目录名为”extra”:
    sudo mkdir /usr/share/ca-certificates/extra
    //然后将待安装的证书拷贝到刚刚创建的目录下:(注意这里的证书是.crt的扩展名)
    sudo cp root.crt /usr/share/ca-certificates/extra/root.crt
    //接下来让ca-certificates工具帮我们安装CA证书: 选择”Yes”,我们能看到待安装的CA证书已经被扫描到了,选中它(点空格键)然后选”OK”就行了。
    sudo dpkg-reconfigure ca-certificates

    运行结果:

     下载 https://download.csdn.net/download/dz45693/14012026  https://github.com/dz45693/dotnetHttpcert.git

    备注:分别在客户端或服务端安装根证书,windows上安装证书时,证书存储可选择“受信任的根证书颁发机构”(我就是没有注意这一点搞了我1天多啊)

    Go的调用

    go需要的证书格式是pem, 我用上面的证书 搞成pem后面有些错误,然后尝试让C# 使用SAN的证书【证书生成请参考】,结果发现可以通过,然后生成C#的pfx文件

     openssl pkcs12 -export -in server.pem -inkey server.key -out server.pfx
    openssl pkcs12 -export -in client.pem -inkey client.key -out client.pfx

    main.go的代码如下(代码本来没有难度, 关键是证书转换):

    package main
     
    import (
        "crypto/tls"
        "crypto/x509"
        "fmt"
        "io/ioutil"
        "log"
        "net/http"
        "time"
     
        "golang.org/x/net/http2"
    )
     
    func main() {
        clientCertFile := "client.pem"
        clientKeyFile := "client.key"
        caCertFile := "ca.pem"
        var cert tls.Certificate
        var err error
        if clientCertFile != "" && clientKeyFile != "" {
            cert, err = tls.LoadX509KeyPair(clientCertFile, clientKeyFile)
            if err != nil {
                fmt.Println(err)
                log.Fatalf("Error creating x509 keypair from client cert file %s and client key file %s", clientCertFile, clientKeyFile)
            }
        }
        caCert, err := ioutil.ReadFile(caCertFile)
        if err != nil {
            fmt.Printf("Error opening cert file %s, Error: %s", caCertFile, err)
        }
        caCertPool := x509.NewCertPool()
        caCertPool.AppendCertsFromPEM(caCert)
        t := &http2.Transport{
            TLSClientConfig: &tls.Config{
                Certificates: []tls.Certificate{cert},
                RootCAs:      caCertPool,
            },
        }
     
        client := http.Client{Transport: t, Timeout: 15 * time.Second}
        resp, err := client.Get("https://localhost:5001/WeatherForecast")
        if err != nil {
            fmt.Printf("Failed get: %s
    ", err)
        }
        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            fmt.Printf("Failed reading response body: %s
    ", err)
        }
        fmt.Printf("Client Got response %d: %s %s
    ", resp.StatusCode, resp.Proto, string(body))
     
    }

    运行结果 :

    参考:

    https://www.cnblogs.com/axzxs2001/p/10070562.html

  • 相关阅读:
    北京初“探”,还是初“谈”
    hadoop集群安装(多机,非伪集群)
    iOS8下注冊push方式变更
    Linux文件编辑命令具体整理
    HDU 1260
    二叉树遍历(前序、中序、后序、层次、深度优先、广度优先遍历)
    关于Linux静态库和动态库的分析
    JavaScript特效之前进,后退(返回上一级)
    具体解释Hibernate中的事务
    iOS开发
  • 原文地址:https://www.cnblogs.com/majiang/p/14220706.html
Copyright © 2011-2022 走看看