.Net gRPC使用证书文件验证详细教程

继上一篇文章 玩转.Net gRPC简单使用详细教程

我这里找到一段脚本用来 生成证书文件

Write-Host "Creating Certificates for Self-Signed Testing" 

Write-Host "Createing Root Certificate"
$cert = New-SelfSignedCertificate -Type Custom -KeySpec Signature `
-Subject "CN=localhost" `
-FriendlyName "gRPCDemoRootCert" `
-KeyExportPolicy Exportable `
-HashAlgorithm sha256 `
-KeyLength 4096 `
-CertStoreLocation "cert://currentuser/My" `
-KeyUsageProperty Sign `
-KeyUsage CertSign `
-NotAfter (Get-Date).AddYears(1)

# Client Auth
Write-Host "Createing Client Auth Certificate"
$clientCert = New-SelfSignedCertificate -Type Custom `
-KeySpec Signature `
-Subject "CN=localhost" `
-KeyExportPolicy Exportable `
-FriendlyName "gRPCDemoClientCert" `
-HashAlgorithm sha256 `
-KeyLength 2048 `
-NotAfter (Get-Date).AddMonths(12) `
-CertStoreLocation "cert://currentuser/My" `
-Signer $cert `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2")

# TLS Cert
Write-Host "Createing Web Server Certificate"
$webCert = New-SelfSignedCertificate -Type Custom `
-Subject "CN=localhost" `
-KeyExportPolicy Exportable `
-DnsName "localhost" `
-FriendlyName "gRPCDemoTlsCert" `
-HashAlgorithm sha256 `
-KeyLength 2048 `
-KeyUsage "KeyEncipherment", "DigitalSignature" `
-NotAfter (Get-Date).AddMonths(12) `
-CertStoreLocation "cert://currentuser/My" `
-Signer $cert

$PFXPass = ConvertTo-SecureString -String "P@ssw0rd!" -Force -AsPlainText

Write-Host "exporting Certificates to file"

Export-PfxCertificate -Cert $clientCert `
-Password $PFXPass `
-FilePath gRPCDemoSelfCert.pfx

Export-PfxCertificate -Cert $webCert `
-Password $PFXPass `
-FilePath gRPCDemoSslCert.pfx


-Subject :使用到的网站
-FriendlyName :名称
-CertStoreLocation 证书存储的位置
$PFXPass 设置的密码

以管理员身份执行:.\Generate_cert.ps1

可能会出现以下错误:

执行 set-executionpolicy remotesigned  即可

生成好后把 gRPCDemoSelfCert.pfx放到客户端,gRPCDemoSslCert.pfx放服务端目录下

文件属性都如图设置下:

 

打开certmgr证书

把root证书拖到受信任的根证书下

 

 

服务端中 Program.cs

 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                    webBuilder.ConfigureKestrel(opt =>
                    {
                        var cert = new X509Certificate2("gRPCDemoSslCert.pfx", "P@ssw0rd!");
                        opt.ConfigureHttpsDefaults(h=> {
                            h.ClientCertificateMode = Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode.AllowCertificate;
                            h.CheckCertificateRevocation = false;
                            h.ServerCertificate = cert;
                        });
                    });
                });

Startup.cs

services.AddAuthentication()
                 .AddCertificate(opt =>
                 {
                     opt.RevocationMode = X509RevocationMode.NoCheck;
                     opt.AllowedCertificateTypes = CertificateTypes.SelfSigned;
                     opt.Events = new CertificateAuthenticationEvents()
                     {
                         OnCertificateValidated = context =>
                         {
                             context.Success();
                             return Task.CompletedTask;
                         }
                     };
                 });

 

Nuget安装  Microsoft.AspNetCore.Authentication.Certificate

MyEmployeeService.cs 中头上加上:

 [Authorize(AuthenticationSchemes =CertificateAuthenticationDefaults.AuthenticationScheme)]
    public class MyEmployeeService : EmployeeServiceBase

 

接下来客户端

           var cert = new X509Certificate2("gRPCDemoSelfCert.pfx", "P@ssw0rd!");
            var handler = new HttpClientHandler();
            handler.ClientCertificates.Add(cert);

            var httpClient = new HttpClient(handler);



            using var channel = GrpcChannel.ForAddress("https://localhost:5001",new GrpcChannelOptions { 
                HttpClient = httpClient
            });

 

把之前的Jwt验证注释掉

public static async Task GetByNoAsync(EmployeeService.EmployeeServiceClient client)
        {
           
            //if (!NeedToken()|| await GetTokenAsync(client))
            //{
                var headers = new Metadata
                {
                    {"Authorization",$"Bearer {_token}" }
                };
                var response = await client.GetByNoAsync(new GetByNoRequest()
                {
                    No = 1994
                }, headers);

                Console.WriteLine(response);
            //}
            
        }

 

运行 dotnet run 1

 

 

大功告成!