Running my ReCAPTCHA routine in VS2012 (VB.Net), I get the error
The underlying connection was closed. An unexpected error occurred on
a receive
This code has been working for several weeks, and now this week has decided to give me the above error.
Can somebody give me an idea of what the problem is? Thanks!
Here is my code:
Dim recaptchaResponse As String = Request.Form("g-recaptcha-response")
If Not String.IsNullOrEmpty(recaptchaResponse) Then
Dim request As Net.WebRequest = Net.WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret={MySecretKey}&response=" + recaptchaResponse)
request.Method = "POST"
request.ContentType = "application/json; charset=utf-8"
Dim postData As String = ""
'get a reference to the request-stream, and write the postData to it
Using s As IO.Stream = request.GetRequestStream()
Using sw As New IO.StreamWriter(s)
sw.Write(postData)
End Using
End Using
'**This next line of code triggers the error**
Using s As IO.Stream = request.GetResponse().GetResponseStream()
Using sr As New IO.StreamReader(s)
'decode jsonData with javascript serializer
Dim jsonData = sr.ReadToEnd()
If jsonData.IndexOf("{" & vbLf & " ""success"": true,") > -1 Then
Return True
Else
lblError.Text = jsonData
End If
End Using
End Using
The inner exception is:
System.ComponentModel.Win32Exception (0x80004005): The client and server cannot communicate, because they do not possess a common algorithm at System.New.SSPIWrapper.AcquireCredentialsHandle
I discovered that the network admin guys decided to implement the ban on TLS 1.0 protocol without telling me.
The fix for this problem is to ensure that ReCAPTCHA communicates via TLS 1.2. This was accomplished with an extra line of code at the top of the routine:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Related
A while ago I wrote a programme in VB.NET to use the Betfair Exchange API. It has worked perfectly for months, but overnight on Tuesday it stopped working. I can still log in, but from Wednesday I have been unable to get anything else from the server.
Betfair are investigating, but according to them nobody else seems to be experiencing the same problem - although I'm not sure how many will be using VB.NET.
Below is the function I have been using to obtain data from the API. Like I said it was working on Tuesday night but not from Wednesday morning. Is there anything here which is "not perfect" or "could be better", or perhaps there is some alternative code I could try? Or is there something which might have happened on my pc which has caused the problem?
The programme falls over at the line "dataStream = request.GetRequestStream() ". The error is "Received an unexpected EOF or 0 bytes from the transport stream."
I would be grateful for any advice that anyone could offer. Thank you!
Public Function CreateRequest(ByVal postData As String, Optional ByVal accountsApi As Boolean = False)
Dim Url As String = "https://api.betfair.com/exchange/betting/json-rpc/v1"
If accountsApi Then Url = "https://api.betfair.com/exchange/account/json-rpc/v1"
Dim request As WebRequest = Nothing
Dim dataStream As Stream = Nothing
Dim response As WebResponse = Nothing
Dim strResponseStatus As String = ""
Dim reader As StreamReader = Nothing
Dim responseFromServer As String = ""
Try
request = WebRequest.Create(New Uri(Url))
request.Method = "POST"
request.ContentType = "application/json-rpc"
request.Headers.Add(HttpRequestHeader.AcceptCharset, "ISO-8859-1,utf-8")
request.Headers.Add("X-Application", appKey)
request.Headers.Add("X-Authentication", sessToken)
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData) ' Data to post such as ListEvents, ListMarketCatalogue etc
request.ContentLength = byteArray.Length ' Set the ContentLength property of the WebRequest.
dataStream = request.GetRequestStream() ' Get the request stream.
dataStream.Write(byteArray, 0, byteArray.Length) ' Write the data to the request stream.
dataStream.Close() ' Close the Stream object.
response = request.GetResponse() ' Get the response.
strResponseStatus = CType(response, HttpWebResponse).StatusDescription ' Display the status below if required
dataStream = response.GetResponseStream() ' Get the stream containing content returned by the server.
reader = New StreamReader(dataStream) ' Open the stream using a StreamReader for easy access.
responseFromServer = reader.ReadToEnd() ' Read the content.
reader.Close() : dataStream.Close() : response.Close()
Catch ex As Exception
MsgBox("CreateRequest Error" & vbCrLf & ex.Message, MsgBoxStyle.Critical, " Error")
End Try
Return responseFromServer
End Function
I would check that the provider hasn't recently deprecated use of TLS 1.0 (as they should have done before now, in fact).
If so, your code needs to enforce use of TLS 1.1+:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
This only has to be set once, usually in the (static) type initializer or similar.
And I 100% agree with Andrew Mortimer that you should use Using blocks wherever possible. I'd also suggest moving all of your string values into variables or constants to clean things up and keep them maintainable. Eg:
Const ContentType As String = "application/json-rpc"
...
request.ContentType = ContentType
UPDATE
I just found this announcement on their site:
https://forum.developer.betfair.com/forum/developer-program/announcements/33563-tls-1-0-no-longer-supported-from-1st-december-all-betfair-api-endpoints
If you are allowed to use external dependencies within this project I would recommend using RestSharp nuget package it works really well for creating API requests and getting there response without having to use httpclient which gets messy.
Link: https://restsharp.dev/
Im trying to use the Blue Prism object HTTP request to get an access token for further processing the items. However, i couldn't manage to get the token due to the error 'The given key was not present in the dictionary'. I have looked all parameters and still didn't manage to solve the issue. I use a built in visual basic code to get the result as a collection which is later parsed to JSON to get the token.
The underlying visual basic code is:
Dim request As WebRequest = WebRequest.Create(addressURL)
If forcePreAuth Then
'Sometimes a web server will require the authorisation header in the initial request
'In which case we have to add the basic authorization header manually.
Dim bytes() As Byte = System.Text.Encoding.UTF8.GetBytes(String.Format("{0}:{1}",username,password))
Dim base64 As String = Convert.ToBase64String(bytes)
request.Headers.Add("Authorization", "Basic " & base64)
Else
If Not String.IsNullOrEmpty(username) AndAlso Not String.IsNullOrEmpty(password) Then
request.Credentials = New NetworkCredential(username,password)
End If
End If
If useProxy Then
Dim proxyURI As New Uri(proxyURL)
Dim proxy As New WebProxy(proxyURI, True)
Dim proxyCred As New NetworkCredential(proxyUsername, proxyPassword)
Dim credCache As New CredentialCache()
credCache.Add(proxyURI, "Basic", proxyCred)
proxy.UseDefaultCredentials = False
proxy.Credentials = credCache
request.Proxy = proxy
End If
request.Method = method
request.ContentType = contentType
Dim httpRequest As HttpWebRequest = TryCast(request, HttpWebRequest)
If httpRequest IsNot Nothing Then
If Not String.IsNullOrEmpty(accept) Then
httpRequest.Accept = accept
End If
If Not String.IsNullOrEmpty(certID) Then
httpRequest.ClientCertificates.Add(m_Certificates(certID))
End If
End If
For Each r As DataRow In headers.Rows
For Each c As DataColumn In headers.Columns
Dim columnName As String = c.ColumnName
Dim val As String = r(columnName).ToString
request.Headers.Add(columnName,val)
Next
Exit For 'Only one row is allowed
Next
If Not String.IsNullOrEmpty(body) Then
Dim requestStream As IO.Stream = request.GetRequestStream()
Using sw As New IO.StreamWriter(requestStream, New Text.UTF8Encoding(False))
sw.Write(body)
End Using
End If
Using response As WebResponse = request.GetResponse()
Dim responseStream As IO.Stream = response.GetResponseStream()
Dim sr As New IO.StreamReader(responseStream)
resultData = sr.ReadToEnd()
End Using
Screenshots:
Input parameter
Input parameter request token
Request token:
Output parameter:
Blue Prism uses a bit of a peculiar pattern regarding Certificates. The way the Utility - HTTP object is designed is to allow for the loading of certificate files (.cer, etc) on-the-fly into a local Certificate Store, which assigns a new Certificate ID each time.
Before firing your HTTP Request, use the Load Certificate action within the same Utility - HTTP object to output a valid Certificate ID, which you can then pass to HTTP Request's Certificate ID parameter.
I need to make a query by getting to an api rest with authorization bearer, the problem is that the vb.net code returns an error in the GetResponse.
ERRORS:
The connection is terminated: Unexpected shipping error.
IOException: Unable to write data to the transport connection: The interruption of an existing connection has been forced by the remote host.
SocketException: The interruption of an existing connection has been forced by the remote host**
I'm not sure the code is correct since I have not found very good examples on the internet ...
I would appreciate the help of someone who understands a bit more than me about the topic
Thanks for all!
Dim s As HttpWebRequest
Dim r As HttpWebResponse
Dim reader As StreamReader
s = HttpWebRequest.Create("https://xxxx.xxxx.net/api/v1/PrivilegedCustomers/byIdentity/D/04400012680")
s.Method = "GET"
s.Headers.Add("Authorization", "Bearer " & Token())
's.ContentType = "application/x-www-form-urlencoded"
r = DirectCast(s.GetResponse(), HttpWebResponse)
reader = New StreamReader(r.GetResponseStream())
Dim json_api As String = reader.ReadToEnd()
Dim json As JObject = JObject.Parse(json_api)
When i make third party request to some URL then IIS gives me error:
The request was aborted: Could not create SSL/TLS secure channel.
however i am able to make request to same URL from console application and Postman.
Dim certificates As X509Certificate2 = New X509Certificate2()
Dim uriPath As String = "D:\CertificateFolder\MyCert.cer"
Dim localPath As String = New Uri(uriPath).LocalPath
certificates.Import(localPath)
Dim sResult As String = ""
Dim activeProtocol As SecurityProtocolType =
ServicePointManager.SecurityProtocol
Try
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 Or
SecurityProtocolType.Tls11
Dim oRequest As HttpWebRequest =
WebRequest.Create("https://test.com/router.dll")
oRequest.KeepAlive = False
oRequest.Method = "POST"
oRequest.ContentType = "text/xml"
Dim Test As String = "some xml"
Dim bytes As Byte() = Text.Encoding.UTF8.GetBytes(Test)
oRequest.ContentLength = bytes.Length
oRequest.ClientCertificates = New X509CertificateCollection({certificates})
Dim oWriter As StreamWriter
Try
Dim streamToSend As Stream = oRequest.GetRequestStream()
oWriter = New StreamWriter(oRequest.GetRequestStream())
streamToSend.Write(bytes, 0, bytes.Length)
streamToSend.Close()
Catch up As Exception
Return
Finally
End Try
Dim oResponse As HttpWebResponse = oRequest.GetResponse()
Dim oReader As New StreamReader(oResponse.GetResponseStream())
sResult = oReader.ReadToEnd
oReader.Close()
Catch
' do nothing for now
Finally
ServicePointManager.SecurityProtocol = activeProtocol
End Try
Note* Method in URL is not file. Method name has .dll just as name of method.
I am using .net framework 4.5
Do you have access to the server management?
Could you first try to connect without providing the client certificate?
Remove the corresponding part from your code and turn off the client certificate requirement in the IIS management console.
If the error still persist, find out which cipher suits the client supports and which the server. If they don't much an error similar to yours would occur.
To check the client, rewrite your code to connect to the following site:
"https://howsmyssl.com/a/check"
If your server you are connection to is public (internet visible), you can use the following site to check its supported cipher suits:
https://www.ssllabs.com/ssltest/
I get
'underlying connection was closed'
when running the code below. I am using vb.net 2012 (I must use this version) with the RestSharp library and am trying to retrieve product data from a bigcommerce.com store. This is a simple vb.net 2012 console program that once I get working I can build upon. I have tried changing around the code somewhat even making certain things redundant like the method and URL but I can't get it to work.
Dim client As New RestClient
client.BaseUrl = New Uri("https://api.bigcommerce.com/stores/mystorehash/v3/catalog/products")
Dim request As New RestRequest("https://api.bigcommerce.com/stores/mystorehash/v3/catalog/products", Method.GET)
request.AddHeader("Accept", "application/json")
request.AddHeader("Content-Type", "application/json")
request.AddHeader("X-Auth-Client", "notactualvaluenotactualvalue")
request.AddHeader("X-Auth-Token", "notactualvaluenotactualvalue")
request.Method = Method.GET
Dim response As New RestResponse
response = client.ExecuteAsGet(request, Method.GET)
Console.WriteLine("response.Content=" & response.Content)
Console.WriteLine("response.ErrorMessage=" & response.ErrorMessage)
Console.WriteLine("response.ResponseStatus=" & response.ResponseStatus)
Console.WriteLine("response.IsSuccessful=" & response.IsSuccessful)
Console.WriteLine("response.Headers.Count=" & response.Headers.Count)
Output:
Any help would be appreciated, hopefully I'm doing something stupid that can be easily fixed
For anyone else that finds this the full implementation of Nathan Booker's suggestion is below. When you attempt to access the Big Commerce api in a VB.NET application you need to specify TLS 1.2. If you don't you'll recieve an HTTP status of 502 - System.IO.IOException Authentication failed because the remote party has closed the transport stream. The solve is done like:
ServicePointManager.Expect100Continue = True
ServicePointManager.SecurityProtocol = CType(3072, SecurityProtocolType)
ServicePointManager.DefaultConnectionLimit = 9999
Dim request As HttpWebRequest = CType(WebRequest.Create("https://api.bigcommerce.com/stores/<Redacted>/v3/catalog/products"), HttpWebRequest)
request.AllowAutoRedirect = True
request.ContentType = "application/json"
request.Accept = "application/json"
request.Method = "GET"
request.Headers.Add("X-Auth-Client", "<Redacted>")
request.Headers.Add("X-Auth-Token", "<Redacted>")
Dim response As WebResponse = request.GetResponse()
Diagnostics.Debug.WriteLine((CType(response, HttpWebResponse)).StatusDescription)
Dim dataStream As Stream = response.GetResponseStream()
Dim reader As StreamReader = New StreamReader(dataStream)
Dim responseFromServer As String = reader.ReadToEnd()
Diagnostics.Debug.WriteLine(responseFromServer)
reader.Close()
response.Close()
This may be related to your HTTP version or (more likely) SSL/TLS protocol.
If possible, please make sure you're using HTTP 1.1 and TLS 1.2.