我在Windows上运行以下websocket客户端代码,一切正常 – 就像预期的那样.但如果代码是为linux-arm发布并复制到RaspberryPi3(在Raspian下运行),它将最终出现在AuthenticationException中.
连接尝试:(抛出异常的点)
private readonly ClientWebSocket _socket;
public ApiConnection()
{
_socket = new ClientWebSocket();
}
public async Task Connect()
{
// the uri is like: wss://example.com/ws
await _socket.ConnectAsync(new Uri(_settings.WebSocketUrl),CancellationToken.None);
if (_socket.State == WebSocketState.Open)
Console.WriteLine("connected.");
}
异常堆栈:
System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message,AsyncProtocolRequest asyncRequest,ExceptionDispatchInfo exception)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message,AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming,Int32 count,AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer,AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer,Int32 readBytes,AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer,AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message,AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from prevIoUs location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar,Func`2 endFunction,Action`1 endAction,Task`1 promise,Boolean requiresSynchronization)
--- End of stack trace from prevIoUs location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.WebSocketHandle.IoUs location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.ClientWebSocket.IoUs location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
目标websocket服务器在Ubuntu上的Nginx代理后面运行.我认为问题依赖于客户端,因为如果代码在Windows上执行,一切正常.
我还尝试将CA证书导入Raspians“证书库”.没有运气.
更新:
http连接(ws://)也适用于linux.看来,WebSocketClient不信任我的LetsEncrypt证书?
要测试,在浏览器中的同一站点上加载相同的url / a url,您应该收到警告.
证书问题解决后,警告将消失.
解决SSL证书问题的确切过程取决于很多事情,比如…
操作系统,Web服务器,证书颁发机构,证书提供商门户网站,因此这里的任何人都几乎不可能为您提供有关修复证书问题的详细信息,但是说……
然而,在SE网络上有一些关于此的一般性建议……
https://unix.stackexchange.com/questions/90450/adding-a-self-signed-certificate-to-the-trusted-list
https://unix.stackexchange.com/questions/17748/trust-a-self-signed-pem-certificate
在你的情况下,由于rasbian基于debian,一些标准的debian建议可能会有所帮助……
在Debian中,证书存储位于/ etc / ssl / certs /中.该目录默认包含一系列符号链接,这些符号链接指向由ca-certificates包安装的证书(包括由c_rehash(1)生成的所需符号链接)和ca-certificates.crt,它是所有这些证书的串联.由update-ca-certificates(8)命令管理的所有内容都负责更新符号链接和ca-certificates.crt文件.
将新的(CA)证书添加到存储非常容易,因为update-ca-certificates(8)也在/usr/local / share / ca-certificates /中查找文件,管理员只需将新证书放入此目录中的PEM格式(扩展名为.crt)并以root身份运行update-ca-certificates(8).系统上的所有应用程序(wget,…)现在应该信任它.
另一个可能的解决方案可能是“我相信我的代码不会请求错误的网址,所以我会忽略SSL证书错误”,你可以用这样的东西做…
…但这并不理想,至少它会让你解决问题,直到你可以解决问题,最糟糕的情况是你仍然可以检查,但是通过编码你自己的支票,而不仅仅是一揽子返回真实.
最后一点:
我经常发现无论操作系统是什么,做一些像重启一样简单的事情,或者在测试/检查之间进行两次操作可以清除一些你通常不会认为是问题的东西.