因为Grpc采用HTTP/2作为通信协议,默认采用LTS/SSL加密方式传输,比如使用.net core启动一个服务端(被调用方)时:  

    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<Startup>();
});

  其中使用UseHttps方法添加证书和秘钥。

  但是,有时候,比如开发阶段,我们可能没有证书,或者是一个自己制作的临时测试证书,那么在客户端(调用方)调用是可能就会出现下面的异常:  

  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, 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.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslStream.ThrowIfExceptional()
at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
  ..........

  然而我们可能没有办法得到有效的证书,这时,我们有两个办法:

  1、使用http协议

  想想,我们为什么要使用Grpc?因为高性能,高效率,简单易用吧,但是https相比http就是多个加密的过程,这可能会有一定的性能损失(一般可忽略)。

  而一般的,我们在微服务架构中使用Grpc比较多,而微服务一般部署在我们自己的一个子网下,这也就没必要使用https了吧?

  具体可参考我上一篇:.net core中Grpc使用报错:The response ended prematurely.

  2、调用时不对证书进行验证

  如果是控制台程序,我们可以这么做:  

    public static void Main(string[] args)
{
var channel = GrpcChannel.ForAddress("https://localhost:5000", new GrpcChannelOptions()
{
HttpClient = null,
HttpHandler = new HttpClientHandler
{
//方法一
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
//方法二
//ServerCertificateCustomValidationCallback = (a, b, c, d) => true
}
}); var client = new Greeter.GreeterClient(channel);
var result = client.SayHello(new HelloRequest() { Name = "Grpc" });
}

  其中 HttpClientHandler 的 ServerCertificateCustomValidationCallback 是对证书的自定义验证,上面给出了两种方式验证。

  如果是.net core的webmvc或者webapi程序,因为.net core 3.x开始已经支持了Grpc的引入,所以我只需要在ConfigureServices中注入Grpc的客户端是进行设置:  

    public void ConfigureServices(IServiceCollection services)
{
services.AddGrpcClient<Greeter.GreeterClient>(nameof(Greeter.GreeterClient), options =>
{
options.Address = new Uri("https://localhost:5000");
}).ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler
{
//方法一
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
//方法二
//ServerCertificateCustomValidationCallback = (a, b, c, d) => true
};
}); ...
}

  因为.net core3.x中Grpc的使用是基于它的HttpClient机制,比如 AddGrpcClient 方法返回的就是一个 IHttpClientBuilder 接口对象,上面的配置我们还可以这么写:  

    public void ConfigureServices(IServiceCollection services)
{
services.AddGrpcClient<Greeter.GreeterClient>(nameof(Greeter.GreeterClient));
services.AddHttpClient(nameof(Greeter.GreeterClient), httpClient =>
{
httpClient.BaseAddress = new Uri("https://localhost:5000");
}).ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler
{
//方法一
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
//方法二
//ServerCertificateCustomValidationCallback = (a, b, c, d) => true
};
}); ...
}

  总之,不管怎么调用,机制都是一样的,最终都是像上面的客户端调用一样去创建Client,只要能理解就好了。

.net core中Grpc使用报错:The remote certificate is invalid according to the validation procedure.的更多相关文章

  1. .net core中Grpc使用报错:The response ended prematurely.

    当我们调用Grpc是出现下面的一堆异常时,一般是由于LTS导致的: Call failed with gRPC error status. Status code: 'Unavailable', Me ...

  2. .net core中Grpc使用报错:Request protocol 'HTTP/1.1' is not supported.

    显然这个报错是说HTTP/1.1不支持. 首先,我们要知道,Grpc是Google开源的,跨语言的,高性能的远程过程调用框架,它是以HTTP/2作为通信协议的,所以当我启动启用一个服务作为Grpc的服 ...

  3. 记一次GRPC使用报错排查

    项目一直使用grpc作为服务交互程序,其中我负责的java模块第一次引用该框架:当框架搭建好后,建立客户端代码,报错: Runable Error:java.lang.IllegalAccessErr ...

  4. Android中editText使用报错

    在activity_main.xml文件中添加了editText控件 <EditText        android:id="@+id/edit_text"        ...

  5. jQuery中live()使用报错,TypeError: $(...).live is not a function

    原博文 https://blog.csdn.net/sdfdyubo/article/details/59536781 使用 原写法 /*为选项卡绑定右键*/ $(".tabs li&quo ...

  6. msf中arp_sweep使用报错:usbmon1:ERROR while getting interface flags:no such device

    在许多的工具使用中,会出现很多的错误,要养成先思考再去寻找帮助的习惯 在用use命令使用arp_sweep模块的时候爆出错误:usbmon1:ERROR while getting interface ...

  7. Windows下Git使用报错:warning:LF will be replaced by CRLF in ××××.××

    Windows下Git使用报错: warning:LF will be replaced by CRLF in ××××.××(文件名) The file will have its original ...

  8. adb驱动安装和使用报错笔记

    adb驱动安装 adb驱动下载地址:https://adb.clockworkmod.com/ 安装时候选择一个容易记住的路径,这个很重要,因为adb驱动没有自动配置环境变量,所以实验时候将adb安装 ...

  9. animate is not a function(zepto 使用报错)[转]

    animate is not a function(zepto 使用报错) 1.为什么使用zepto写animate报错? 因为zepto默认构建包含: Core, Ajax, Event, Form ...

随机推荐

  1. Android 基础UI组件(二)

    1.Spinner 提供一个快速的方法来从一组值中选择一个值.在默认状态Spinner显示当前选择的值.触摸Spinner与所有其他可用值显示一个下拉菜单,可以选择一个新的值. /** * 写死内容: ...

  2. mysqldump冷备份

    数据库备份的重要性 提高系统的高可用性和灾难可恢复性,在数据库系统崩溃时,没有数据备份就没法找到数据. 使用数据库备份还原数据库,是数据库崩溃时提供数据恢复最小代价的最优方案. 没有数据库就没有一切, ...

  3. jmeter进阶

    1.如果(if)控制器的使用     2.参数的调用 3.数据库的链接

  4. 为Python的web框架编写前端模版的教程

    虽然我们跑通了一个最简单的MVC,但是页面效果肯定不会让人满意. 对于复杂的HTML前端页面来说,我们需要一套基础的CSS框架来完成页面布局和基本样式.另外,jQuery作为操作DOM的JavaScr ...

  5. Shell脚本定期清空大于1G的日志文件

    一个关于如何在指定文件大于1GB后,自动删除的问题. 批处理代码如下: #!/bin/bash # 当/var/log/syslog大于1GB时 # 自动将其备份,并清空 # 注意这里awk的使用 i ...

  6. 『与善仁』Appium基础 — 20、Appium元素定位

    目录 1.by_id定位 2.by_name定位 3.by_class_name定位 4.by_xpath定位 5.by_accessibility_id定位 6.by_android_uiautom ...

  7. HGAME2021 week4 pwn writeup

    第四周只放出两道题,也不是很难. house_of_cosmos 没开pie,并且可以打got表. 在自写的输入函数存在漏洞.当a2==0时,因为时int类型,这里就会存在溢出.菜单题,但是没有输出功 ...

  8. [BUUCTF]PWN18——bjdctf_2020_babystack

    [BUUCTF]PWN18--bjdctf_2020_babystack 附件 步骤: 例行检查,64位,开启了nx保护 试运行一下程序 大概了解程序的执行过程后用64位ida打开,shift+f12 ...

  9. 3、回溯算法解题套路框架——Go语言版

    前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...

  10. Python3 json &pickle 数据序列化

    json 所有语言通用的信息交换格式 json.dumps()将list列表.dict字典.元组.函数等对象转换为可以存储的字符格式存入文件 json.dump(数据对象名,已以写方式打开的对象) 直 ...