基于最新Semantic Kernel的C#应用出现SSL连接错误的解决方案咨询
开发了一个基于Microsoft Semantic Kernel NuGet包的C#控制台应用,可在控制台窗口接收文本内容,提交至Semantic Kernel/OpenAI并返回结果。该应用在家中运行正常,但在工作电脑上调用GetStreamingChatMessageContentsAsync方法时,抛出未处理异常:System.ClientModel.ClientResultException: 无法建立SSL连接。执行代码并输入"Hello"时触发该错误,完整异常信息如下。咨询微软相关人员后无法确定具体原因,推测可能与反向代理有关,求解决办法。
核心代码
using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.ChatCompletion; using System; using AiPlayground; using Microsoft.SemanticKernel.Connectors.OpenAI; var builder = Kernel.CreateBuilder(); var modelId = "gpt-4o-mini"; var secret = @"fakesecret-fakesecret"; // Services builder.AddOpenAIChatCompletion(modelId: modelId, apiKey: secret); Kernel kernel = builder.Build(); var chatService= kernel.GetRequiredService<IChatCompletionService>(); var chatMessages = new ChatHistory(); chatMessages.AddSystemMessage("You are Jerry Seinfeld and you like to talk about insureds and policies"); while (true) { Console.Write("Prompt:"); chatMessages.AddUserMessage(Console.ReadLine()); var result = chatService.GetStreamingChatMessageContentsAsync(chatMessages, executionSettings: new OpenAIPromptExecutionSettings { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions },kernel:kernel); var fullMessage = ""; await foreach (var content in result) { Console.Write(content); fullMessage += content; } chatMessages.AddAssistantMessage(fullMessage); Console.WriteLine(); }
完整异常信息
Unhandled exception. System.ClientModel.ClientResultException: The SSL connection could not be established, see inner exception.
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: RevocationStatusUnknown
at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
at System.Threading.Tasks.TaskCompletionSourceWithCancellation1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) at System.ClientModel.Primitives.HttpClientPipelineTransport.ProcessSyncOrAsync(PipelineMessage message, Boolean async) --- End of inner exception stack trace --- at System.ClientModel.Primitives.HttpClientPipelineTransport.ProcessSyncOrAsync(PipelineMessage message, Boolean async) at System.ClientModel.Primitives.HttpClientPipelineTransport.ProcessCoreAsync(PipelineMessage message) at System.ClientModel.Primitives.PipelineTransport.ProcessSyncOrAsync(PipelineMessage message, Boolean async) at System.ClientModel.Primitives.PipelineTransport.ProcessAsync(PipelineMessage message) at System.ClientModel.Primitives.PipelineTransport.ProcessAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex)
at System.ClientModel.Primitives.PipelinePolicy.ProcessNextAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex) at System.ClientModel.Primitives.ApiKeyAuthenticationPolicy.ProcessAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex)
at System.ClientModel.Primitives.PipelinePolicy.ProcessNextAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex) at System.ClientModel.Primitives.ClientRetryPolicy.ProcessSyncOrAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex, Boolean async)
at System.ClientModel.Primitives.ClientRetryPolicy.ProcessSyncOrAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex, Boolean async) at System.ClientModel.Primitives.ClientRetryPolicy.ProcessAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex)
at GenericActionPipelinePolicy.ProcessAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex) at OpenAI.GenericActionPipelinePolicy.ProcessAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex)
at OpenAI.GenericActionPipelinePolicy.ProcessAsync(PipelineMessage message, IReadOnlyList1 pipeline, Int32 currentIndex) at System.ClientModel.Primitives.ClientPipeline.SendAsync(PipelineMessage message) at OpenAI.ClientPipelineExtensions.ProcessMessageAsync(ClientPipeline pipeline, PipelineMessage message, RequestOptions options) at OpenAI.Chat.ChatClient.CompleteChatAsync(BinaryContent content, RequestOptions options) at OpenAI.Chat.ChatClient.<>c__DisplayClass12_0.<<CompleteChatStreamingAsync>g__sendRequestAsync|0>d.MoveNext() --- End of stack trace from previous location --- at OpenAI.Chat.InternalAsyncStreamingChatCompletionUpdateCollection.GetRawPagesAsync()+MoveNext() at OpenAI.Chat.InternalAsyncStreamingChatCompletionUpdateCollection.GetRawPagesAsync()+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at System.ClientModel.AsyncCollectionResult1.GetAsyncEnumerator(CancellationToken cancellationToken)+MoveNext()
at System.ClientModel.AsyncCollectionResult1.GetAsyncEnumerator(CancellationToken cancellationToken)+MoveNext() at System.ClientModel.AsyncCollectionResult1.GetAsyncEnumerator(CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.GetStreamingChatMessageContentsAsync(String targetModel, ChatHistory chatHistory, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)+MoveNext()
at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.GetStreamingChatMessageContentsAsync(String targetModel, ChatHistory chatHistory, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)+MoveNext()
at Microsoft.SemanticKernel.Connectors.OpenAI.ClientCore.GetStreamingChatMessageContentsAsync(String targetModel, ChatHistory chatHistory, PromptExecutionSettings executionSettings, Kernel kernel, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
at Program.$(String[] args) in C:\Users\rickh\source\repos\AiPlayground\AiPlayground\Program.cs:line 40
at Program.$(String[] args) in C:\Users\rickh\source\repos\AiPlayground\AiPlayground\Program.cs:line 40
at Program.(String[] args)
解决办法
从异常信息看,根源是证书链中的吊销状态未知,结合工作环境的反向代理场景,可尝试以下方案:
1. 配置系统代理设置
工作电脑通常通过企业代理访问外网,需确保应用能正确使用代理:
- 检查系统代理设置是否正确,确认能正常访问OpenAI官网
- 若系统自动代理未生效,可在代码中显式指定代理地址:
// 在创建Kernel前添加HttpClient配置 var httpClient = new HttpClient(new HttpClientHandler { Proxy = new WebProxy("http://你的代理地址:端口"), UseProxy = true }); builder.AddOpenAIChatCompletion(modelId, secret).WithHttpClient(httpClient);
2. 信任企业代理证书
企业代理通常会替换SSL证书,导致系统不信任:
- 将代理的根证书导入到工作电脑的受信任根证书颁发机构存储中
- 若无法修改系统证书,可在代码中临时跳过证书验证(仅测试环境使用,生产环境禁用):
var httpClientHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true }; var httpClient = new HttpClient(httpClientHandler); builder.AddOpenAIChatCompletion(modelId, secret).WithHttpClient(httpClient);
3. 禁用证书吊销检查
异常提示RevocationStatusUnknown,说明无法验证证书吊销状态,可尝试关闭吊销检查:
- 通过修改代码中的SSL验证选项实现:
var httpClientHandler = new HttpClientHandler { SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13, CheckCertificateRevocationList = false }; var httpClient = new HttpClient(httpClientHandler); builder.AddOpenAIChatCompletion(modelId, secret).WithHttpClient(httpClient);
4. 检查网络策略限制
联系企业IT部门确认:
- 是否有防火墙或安全策略阻止了对OpenAI API域名的访问
- 是否允许出站的HTTPS流连接(流式接口需要持久连接)
内容的提问来源于stack exchange,提问作者Rick Hodder

