[CLR] .Net framework 2.0 WebClient 連接 https


12 年前工業級設備環境還有 Win2k WorkStation ,當時開發的回傳走 http 是用 .Net framework 2.0 ,2.0 是能安裝在 Windows 2000 或 Windows Me 以前 OS 的最後一個版本,那個年代雖然已經有 https 了,但是用的不多,所以當時回傳資料的程式開發時,就直接這樣用,再於回傳裡面標記檢查資訊。

這周有個客戶希望把資料也扔他們那一份,當初是用節區架構建的,所以在參數檔新增他們的節區即可,這部分是同事處理,連續兩天溝通確認扔不過去,我介入處理後,先調出 log 檔的錯誤訊息。

大概常在網路上讀文章,一看錯誤訊息就推論疑似是 https 問題,檢查網址果然是 https 。

馬上 google 搜尋 WebClient https ,找到黑大的文:

C# 連線 HTTPS 網站發生驗證失敗導致基礎連接已關閉

原則上有兩個解決方向:

  1. 改程式碼,加入 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
  2. 改機碼,設定 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319\SchUseStrongCrypto=dword:00000001

改程式碼部分,搜尋 MSDN 查屬性,在 .Net framework 4.0 前只能設定 Ssl3 跟 Tls ,但就是這兩個加密協定被停用。參考下面連結 (從左邊下拉式可改 .Net 版本)

SecurityProtocolType 列舉

所以改試機碼變更,在 .Net framework 2.0 不吃 SchUseStrongCrypto 。

於是再祭出 google 大神搜尋 WebClient https “.Net framework 2.0″ site:support.microsoft.com ,得到:

TLS 系統預設版本包含在.NET Framework 2.0 SP2,Windows Vista SP2 和 Server 2008 SP2 的支援

這邊是說 .Net framework 2.0 SP2 已經加入相關加密協定支援,機碼用:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v2.0.50727\SystemDefaultTlsVersions"=dword:00000001

即可。

我是跑 32 bits Application On Windows 10 IoT x64 ,所以要改用機碼 (Windows 64 On Windows 32):

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v2.0.50727\SystemDefaultTlsVersions"=dword:00000001

一測試就可以通聯,問題解決關案,還不用改程式碼。

另外這個 KB3154517 有寫到,在 SP2 列舉常數 SecurityProtocolType 已經加入 Tls11 / Tls12 的支援,所以也是可以改原始碼的。

不過事情解決了,就懶得改原始碼,把機碼匯出來,直接變成選項載入。

最後,.Net framework 相關文件都建議停用 WebClient ,改用 HttpClient ,作為本篇附註參考。

錯誤訊息參考:

[2022/03/日期 時:分:02.104] 基礎連接已關閉: 傳送時發生未預期的錯誤。
System
   於 System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
   於 System.Net.WebClient.DownloadData(Uri address)
   於 System.Net.WebClient.DownloadData(String address)
   於 [AppName].[模組].[方法](String sUrl, Object nowQueryEvent)
   於 [AppName].[視窗].[事件]()System.Net.WebException: 基礎連接已關閉: 傳送時發生未預期的錯誤。 ---> System.IO.IOException: 收到來自傳輸資料流的未預期 EOF 或 0 個位元組。
   於 System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   於 System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   於 System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   於 System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   於 System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   於 System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   於 System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   於 System.Net.TlsStream.CallProcessAuthentication(Object state)
   於 System.Threading.ExecutionContext.runTryCode(Object userData)
   於 System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   於 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   於 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   於 System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   於 System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   於 System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   於 System.Net.ConnectStream.WriteHeaders(Boolean async)
   --- 內部例外狀況堆疊追蹤的結尾 ---
   於 System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
   於 System.Net.WebClient.DownloadData(Uri address)
   於 System.Net.WebClient.DownloadData(String address)
   於 [AppName].[模組].[方法](String sUrl, Object nowQueryEvent)
   於 [AppName].[視窗].[事件]()
Categories: 工作點滴, 技術分享 | 標籤: | 1 則迴響

文章分頁導航

1 thoughts on “[CLR] .Net framework 2.0 WebClient 連接 https

  1. 引用通告: [VBA] 抓取 Json 檔案轉入 Excel | 鄭子璉

發表留言

在WordPress.com寫網誌.