我們正在使用Xamarin開發Android應用程序。應用程序通過HTTPS上的HttpWebRequest Post將工作數據發送到後端服務(由證書保護的WCF)。一切正常,直到消息發送超過限制的大小。在這種情況下,在每一個同步,我們得到了以下錯誤之一:帶有證書的Xamarin Android HttpWebClient:System.IO.IOException:認證或解密失敗
System.IO.IOException:身份驗證或解密失敗。 ---> System.IO.IOException:發送TLS警報時發生錯誤(致命:InternalError):System.NullReferenceException:未將對象引用設置爲對象的實例。
System.Net.WebException:獲取響應流時出錯(ReadDone1):ReceiveFailure ---> System.IO.IOException:認證或解密失敗。 ---> System.IO.IOException:發送TLS警報時發生錯誤(致命:InternalError):System.IO.IOException:認證或解密失敗。 ---> System.IO.IOException:無法將數據寫入傳輸連接:由對等方重置連接。 ---> System.Net.Sockets.SocketException:由對等
A「大」的消息導致錯誤連接重置爲44KB(在UTF8 22KB)!
我們已經嘗試:
- 一件事我們注意的是,如果我們只是發送大郵件之前進行的HttpWebRequest後的小消息,它工作正常。
- 使用Restharp進行測試,其行爲相同。 Restharp也使用System.net.dll
- 我們還測試了Postman的消息,導致移動應用程序出現問題並且消息已成功發送。所以這似乎與System.Net有關。
我們發現,其他人似乎有這個問題,解決辦法是使用ModernHttp,但並不適用於我們,因爲它不支持客戶端證書: HttpClient Error getting response stream (ReadDone1): ReceiveFailure
下面Xamarin版本我們使用:
的Visual Studio 2015年更新3
Xamarin 4.2.1.64
Xamarin.Android 7.0.2.37 - 在測試了三星設備S4和S5採用Android 5.0.1和Android 6
有什麼想法嗎?
第一個錯誤堆棧跟蹤:
System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Error while sending TLS Alert (Fatal:InternalError): System.NullReferenceException: Object reference not set to an instance of an object.
at Mono.Security.Protocol.Tls.SslStreamBase.InternalBeginWrite (Mono.Security.Protocol.Tls.SslStreamBase+InternalAsyncResult asyncResult) [0x00031] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:782 ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.AsyncCallback callback, System.Object state) [0x00014] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:907
at Mono.Security.Protocol.Tls.RecordProtocol.BeginSendRecord (Mono.Security.Protocol.Tls.ContentType contentType, System.Byte[] recordData, System.AsyncCallback callback, System.Object state) [0x00026] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:765
at Mono.Security.Protocol.Tls.RecordProtocol.SendRecord (Mono.Security.Protocol.Tls.ContentType contentType, System.Byte[] recordData) [0x00000] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:786
at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (Mono.Security.Protocol.Tls.Alert alert) [0x00027] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:633
at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (System.Exception& ex) [0x00021] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:598
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at Mono.Security.Protocol.Tls.SslStreamBase.InternalBeginWrite (Mono.Security.Protocol.Tls.SslStreamBase+InternalAsyncResult asyncResult) [0x00077] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:791
at Mono.Security.Protocol.Tls.SslStreamBase.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 count, System.AsyncCallback callback, System.Object state) [0x000a3] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:858
at Mono.Net.Security.Private.LegacySslStream.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 count, System.AsyncCallback asyncCallback, System.Object asyncState) [0x00006] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/Mono.Net.Security/LegacySslStream.cs:435
at System.Net.WebConnection.BeginWrite (System.Net.HttpWebRequest request, System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.AsyncCallback cb, System.Object state) [0x0005f] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net/WebConnection.cs:1000
二錯誤堆棧跟蹤:
System.Net.WebException: Error getting response stream (ReadDone1): ReceiveFailure ---> System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Error while sending TLS Alert (Fatal:InternalError): System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer. ---> System.Net.Sockets.SocketException: Connection reset by peer
at System.Net.Sockets.Socket.EndReceive (System.IAsyncResult result) [0x0002d] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net.Sockets/Socket.cs:2031
at System.Net.Sockets.NetworkStream.EndRead (System.IAsyncResult asyncResult) [0x0005f] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:858
--- End of inner exception stack trace ---
at Mono.Security.Protocol.Tls.RecordProtocol.EndReceiveRecord (System.IAsyncResult asyncResult) [0x0003a] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:430
at Mono.Security.Protocol.Tls.SslClientStream.SafeEndReceiveRecord (System.IAsyncResult ar, System.Boolean ignoreEmpty) [0x00000] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs:256
at Mono.Security.Protocol.Tls.SslClientStream.NegotiateAsyncWorker (System.IAsyncResult result) [0x00071] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs:418
--- End of inner exception stack trace ---
at Mono.Security.Protocol.Tls.SslClientStream.EndNegotiateHandshake (System.IAsyncResult result) [0x00035] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs:396
at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (System.IAsyncResult asyncResult) [0x0000c] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:101 ---> System.IO.IOException: Unable to write data to the transport connection: The socket is not connected. ---> System.Net.Sockets.SocketException: The socket is not connected
at System.Net.Sockets.Socket.BeginSend (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socket_flags, System.AsyncCallback callback, System.Object state) [0x00021] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net.Sockets/Socket.cs:2566
at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.AsyncCallback callback, System.Object state) [0x000b4] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:934
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.AsyncCallback callback, System.Object state) [0x000f2] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:954
at Mono.Security.Protocol.Tls.RecordProtocol.BeginSendRecord (Mono.Security.Protocol.Tls.ContentType contentType, System.Byte[] recordData, System.AsyncCallback callback, System.Object state) [0x00026] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:765
at Mono.Security.Protocol.Tls.RecordProtocol.SendRecord (Mono.Security.Protocol.Tls.ContentType contentType, System.Byte[] recordData) [0x00000] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:786
at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (Mono.Security.Protocol.Tls.Alert alert) [0x00027] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:633
at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (System.Exception& ex) [0x00021] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:598
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at Mono.Security.Protocol.Tls.SslStreamBase.EndRead (System.IAsyncResult asyncResult) [0x00051] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:883
at Mono.Net.Security.Private.LegacySslStream.EndRead (System.IAsyncResult asyncResult) [0x00006] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/Mono.Net.Security/LegacySslStream.cs:494
at System.Net.WebConnection.ReadDone (System.IAsyncResult result) [0x0002a] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net/WebConnection.cs:468
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse (System.IAsyncResult asyncResult) [0x0005e] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1023
at System.Net.HttpWebRequest.GetResponse() [0x0000e] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1037
at MyOrg.Logistic.Mobile.Droid.CommunicationUtilities.RestPost[T] (MyOrg.Logistic.Droid.Mobile.ServiceTypes type, Communication.CommServerSettings commServerSettings, System.String requestPath, System.Object parameters, System.Boolean retry, System.Boolean closeHttpConnection) [0x000cf] in C:\Dev\Mobile\Application\main\Application\Mobile.App.Droid\CommunicationUtilities.cs:309
at MyOrg.Logistic.Droid.Mobile.Droid.Service.SendStoreSecondLayerEvent (MyOrg.Logistic.Droid.Messages.StoreSecondLayerEventMessage msg) [0x00001] in C:\Dev\Mobile\Application\main\Application\Mobile.App.Droid\Services\Service.cs:96
at MyOrg.Logistic.Droid.Mobile.SynchronizationExecutionViewModel+<Synchronize>d__38.MoveNext() [0x00173] in C:\Dev\Mobile\Application\main\Application\Mobile.App\ViewModels\SynchronizationExecutionViewModel.cs:172
的HttpWebRequest代碼:
public static T RestPost<T>(ServiceTypes type, CommServerSettings commServerSettings, string requestPath,
object parameters = null, bool retry = false, bool closeHttpConnection = true) where T : new()
{
//https://192.168.1.12:6206/Transmission/StoreSecondLayerEvent
var url = BuildServiceUrl(type,
commServerSettings,
requestPath);
HttpWebRequest.DefaultMaximumResponseHeadersLength = 128 * 1024; // 128kb
//specify to use TLS 1.2 as default connection
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
/* HttpWebRequest Variant */
string output = string.Empty;
if (parameters != null)
{
output = JsonConvert.SerializeObject(parameters);
}
byte[] postDataByteArray = Encoding.UTF8.GetBytes(output);
var rq = new HttpWebRequest(new Uri(url));
if (Certificate != null)
{
rq.ClientCertificates = new X509Certificate2Collection(Certificate);
}
rq.KeepAlive = !closeHttpConnection;
//rq.PreAuthenticate = true;
//rq.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
rq.Method = "POST";
rq.ContentType = "application/json";
rq.ContentLength = postDataByteArray.Length;
// write the data on the connection stream
using (var dataStream = rq.GetRequestStream())
{
dataStream.Write(postDataByteArray, 0, postDataByteArray.Length);
dataStream.Close();
}
string responseString;
using (HttpWebResponse rs = (HttpWebResponse) rq.GetResponse())
{
using (Stream responseStream = rs.GetResponseStream())
{
using (StreamReader responseReader = new StreamReader(responseStream))
{
responseString = responseReader.ReadToEnd();
}
}
}
Console.WriteLine("Received: " + responseString);
var keyResponse = JsonConvert.DeserializeObject<T>(responseString);
return keyResponse;
}
static CommunicationUtilities()
{
try
{
// # Sets the validation of the certificate to be always valid
// # Check: https://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback(v=vs.110).aspx
ServicePointManager.ServerCertificateValidationCallback += (sender,
certificate,
chain,
errors) => true;
}
catch (Exception ex)
{
throw new Exception("Error initializing CommunicationUtilities class!", ex);
}
}
爲什麼不試試HttpClient的? HttpClient可以直接映射到本地處理程序,也可以使用帶有客戶端證書的處理程序。 https://dotnetcodr.com/2016/01/25/using-client-certificates-in-net-part-5-working-with-client-certificates-in-a-web-project/ – BrewMate
現有的WebRequestHandler支持證書在Xamarin Android或PCL項目上不可用。或者我錯了? –