Grpc usage error in .net core: The remote certificate is invalid according to the validation procedure.
Because Grpc uses HTTP/2 as the communication protocol, it adopts LTS/SSL encrypted transmission by default. For example, when using .net core to start a server (callee):
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureKestrel(options => { options.ListenAnyIP(5000, listenOptions => { listenOptions.Protocols = HttpProtocols.Http2; listenOptions.UseHttps("xxxxx.pfx", "password "); }); }); webBuilder.UseStartup(); });
Use the UseHttps method to add certificates and keys.
However, sometimes, such as the development stage, we may not have a certificate, or a temporary test certificate made by ourselves, then the following may appear in the client (caller) call Exception:
Call failed with gRPC error status. Status code: 'Internal', Message: 'Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. AuthenticationException: The remote certificate is invalid according to the validation procedure.'. fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. Grpc.Core.RpcException: Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception .AuthenticationException: The remote certificate is invalid according to the validation procedure.", DebugException="System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure. at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception) at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolReq/span>//Method 2 //ServerCertificateCustomValidationCallback = (a, b, c, d) => true } }); var client = new Greeter. GreeterClient(channel); var result = client.SayHello(new HelloRequest() { Name = "Grpc" }); }
Among them, the ServerCertificateCustomValidationCallback of HttpClientHandler is a custom verification of the certificate, and two ways of verification are given above.
If it is a webmvc or webapi program of .net core, because .net core 3.x has already supported the introduction of Grpc, so I only need to inject the client of Grpc in ConfigureServices to set it up:
public void ConfigureServices(IServiceCollection services) { services.AddGrpcClient(nameof(Greeter.GreeterClient), options => { options.Address = new Uri("https://localhost:5000"); }).ConfigurePrimaryHttpMessageHandler(() => { return new span> HttpClientHandler { //Method 1 ServerCertificateCustomValidationCallback = HttpClientHandler. DangerousAcceptAnyServerCertificateValidator //Method 2 //ServerCertificateCustomValidationCallback = (a, b, c, d) => true }; }); ... }
Because the use of Grpc in .net core3.x is based on its HttpClient mechanism. For example, the AddGrpcClient method returns an IHttpClientBuilder interface object. We can also write the above configuration as follows:
public void ConfigureServices(IServiceCollection services) { services.AddGrpcClient(nameof(Greeter.GreeterClient)); services.AddHttpClient(nameof(Greeter.GreeterClient), httpClient => { httpClient.BaseAddress = new Uri("https://localhost:5000"); }).ConfigurePrimaryHttpMessageHandler(() => { return new span> HttpClientHandler { //Method 1 ServerCertificateCustomValidationCallback = HttpClientHandler. DangerousAcceptAnyServerCertificateValidator //Method 2 //ServerCertificateCustomValidationCallback = (a, b, c, d) => true }; }); ... }
In short, no matter how you call it, the mechanism is the same. In the end, the client is created like the above client call, as long as you can understand it.
No matter how it is called, the mechanism is the same. In the end, the client is created like the above client call, as long as it can be understood.