【问题标题】:HTTP2 .Net Framework issues with gRPCgRPC 的 HTTP2 .Net 框架问题
【发布时间】:2021-12-17 21:33:14
【问题描述】:

我需要使用 gRPC 进行双向流式传输,其中客户端是 .Net Framework 项目,由于遗留问题,无法升级到 .NET5+。

在阅读微软文档时,我可以看到应该使用 WinHttpHandler (https://docs.microsoft.com/en-us/aspnet/core/grpc/netstandard?view=aspnetcore-5.0)。

但我似乎在此设置中使用 SSL 时遇到问题,是否有人建议如何解决此问题?

我收到以下错误:

"InvalidOperationException: GrpcChannel 不支持具有非空参数的 SslCredentials。GrpcChannel 使用 HttpClient 进行 gRPC 调用,并且 HttpClient 自动从操作系统证书存储中加载根证书。客户端证书应在 HttpClient 上配置。见https://aka.ms/aspnet/grpc/certauth了解详情。”

我的服务器设置如下:

let cacert = File.ReadAllText(@"ca.crt");
let servercert = File.ReadAllText(@"server.crt");
let serverkey = File.ReadAllText(@"server.key");

let certificatePair = new KeyCertificatePair(servercert, serverkey);
let certList = new System.Collections.Generic.List<KeyCertificatePair>()
    certList.Add(certificatePair)
let server = new Server()
    server.Services.Add(EventSubscriberService.EventSubscriberServiceMethodBinder.BindService(new EventSubscriber()))
    server.Ports.Add(new ServerPort("localhost", 5001,SslServerCredentials(certList,cacert,false))) 
    |> ignore'''

客户端使用此设置:

let cacert = File.ReadAllText(@"ca.crt");
let clientcert = File.ReadAllText(@"client.crt");
let clientkey = File.ReadAllText(@"client.key");
let ssl = new SslCredentials(cacert, new KeyCertificatePair(clientcert, clientkey))

let channelOptions = GrpcChannelOptions()
channelOptions.HttpHandler <- new WinHttpHandler()    
channelOptions.Credentials <- ssl


let channel = GrpcChannel.ForAddress("http://127.0.0.1:5001",channelOptions)

它是用 F# 编写的,但类似于此 C# 代码,如果引用有助于提高可读性的话。 How to enable server side SSL for gRPC?

【问题讨论】:

    标签: http ssl f# grpc channel


    【解决方案1】:

    大概按照以下思路(草稿)应该可行:

    open System.Net.Http
    open Grpc.Net.Client
    open System.Security.Cryptography.X509Certificates
    
    let clientCert = new X509Certificate() // create according to your needs
    let handler = new HttpClientHandler()
    handler.ClientCertificates.Add(clientCert) |> ignore
    // insecure, check your custom server cert
    handler.ServerCertificateCustomValidationCallback <- fun msg cert chain e -> true
    let client = new HttpClient(handler)
    let channelOptions = GrpcChannelOptions(HttpClient = client)
    let channel = GrpcChannel.ForAddress("http://127.0.0.1:5001", channelOptions)
    

    【讨论】:

    • 似乎可以解决问题。非常感谢!