将旧版HttpWebRequest POST转换为HttpClient异步POST类(VB)

时间:2019-11-28 17:00:55

标签: .net httpwebrequest httpclient

我有一个.net(4.7.2或4.8)控制台应用程序,该应用程序使用HttpWebRequest来发布JWT样式身份验证数据以便检索JSON输出。我在Windows Server 2012盒子上遇到TLS 1.2站点的问题(在Windows 10上可以正常使用),并且建议我升级到HttpClient异步类。我正在努力寻找使用VB的HttpClient POST示例。...仅将代码转换为C#,用HttpClient异步POST代替HttpWebRequest会是什么样? HttpWebRequest的问题所在就是GetAccessToken方法。

任何帮助表示赞赏!

Imports System.Net
Imports System.IO
Imports System.Data.SqlClient
Imports System.Configuration
Imports Newtonsoft.Json.Linq
Imports System.Security.Cryptography

Module Module1

    Public Class myAPIClass

        'API info
        Private API_ClientKey As String = ConfigurationManager.AppSettings("API_ClientKey")
        Private API_ClientSecret As String = ConfigurationManager.AppSettings("API_ClientSecret")
        Private FullURL As String = ConfigurationManager.AppSettings("URL")
        'Quotation Mark Character for substitution
        Private q As Char = Chr(34)
        'JWT Claim Set Parameters
        Property iss As String = API_ClientKey
        Property aud As String = FullURL
        Property AccessToken As String

        Public Sub New()
            GetAccessToken()
        End Sub

        Public Sub GetAccessToken()
            System.Net.ServicePointManager.SecurityProtocol = Net.SecurityProtocolType.Tls12
            Dim uriAddress As New Uri(FullURL)
            Dim wRequest As HttpWebRequest = DirectCast(HttpWebRequest.Create(uriAddress), HttpWebRequest)
            Dim strPostData As String = ""
            Dim bytPostData As Byte()
            Dim stJWT As String
            'Get JWT
            stJWT = CreateJWT()
            'Post Data ---
            strPostData = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer" & "&assertion=" & stJWT
            'Post Data --- to byte()
            bytPostData = System.Text.Encoding.UTF8.GetBytes(strPostData)
            'Set Web Request Properties
            With wRequest
                .Method = "POST"
                .ContentType = "application/x-www-form-urlencoded"
                .ContentLength = bytPostData.Length
            End With

            'Post Request and Get Response
            Using postStream As Stream = wRequest.GetRequestStream()
                postStream.Write(bytPostData, 0, bytPostData.Length)
                Dim rawResponseFromServer = ""
                Try
                    Using response As HttpWebResponse = wRequest.GetResponse()
                        Dim reader As New StreamReader(response.GetResponseStream())
                        rawResponseFromServer = reader.ReadToEnd()
                        Dim o As JObject = JObject.Parse(rawResponseFromServer)
                        Me.AccessToken = o.Item("access_token").Value(Of String)()
                    End Using

                Catch wex As WebException
                    If Not wex.Response Is Nothing Then
                        Console.WriteLine(wex.Message)
                        Console.WriteLine("Resulting Error --- " & wex.Message & vbNewLine & wex.StackTrace)
                    End If
                End Try
            End Using
        End Sub

#Region "HelperFunctions"
        Private Function CreateJWT() As String
            Dim JWT As String
            Dim EncodedJWT As Byte()

            'Build Header and Claim Set String
            Dim strHeader As String = Strings.Replace("{'alg':'HS256','typ':'JWT'}", "'", q)
            Dim strClaimSet As String = Strings.Replace("{'iss':'" & iss & "', 'aud':'" & aud & "', 'exp':" & exp(600) & ", 'iat':" & iat() & "}", "'", q)

            'Build JWT String
            JWT = ToBase64URL(strHeader) & "." & ToBase64URL(strClaimSet)

            'Convert Client Secret to UTF8 Byte()
            Dim bytKey As Byte() = System.Text.Encoding.UTF8.GetBytes(API_ClientSecret)

            'Encode JWT String
            Dim hmac_encode As HMACSHA256 = New HMACSHA256(bytKey)
            EncodedJWT = hmac_encode.ComputeHash(System.Text.Encoding.UTF8.GetBytes(JWT))

            'Sign and return JWT
            Dim signature As String = ToBase64URL(EncodedJWT)
            Return JWT & "." & signature
        End Function

        Private Function ToBase64URL(Text As String) As String

            Dim b As Byte() = System.Text.Encoding.UTF8.GetBytes(Text)
            Return ToBase64URL(b)

        End Function

        Private Function ToBase64URL(byt As Byte()) As String

            Dim result As String
            'Convert to base 64 string
            result = Convert.ToBase64String(byt)
            'Make URL Friendly
            result = result.Replace("+", "-").Replace("/", "_")
            Do While result.Chars(result.Length - 1) = "="
                result = Strings.Left(result, result.Length - 1)
            Loop
            Return result

        End Function

        ReadOnly Property exp(ExpirationSeconds As Integer) As Long
            Get
                Return iat() + ExpirationSeconds
            End Get
        End Property

        ReadOnly Property iat() AsLong
        Get
                Dim StartDate As Date = CDate("1/1/1970")
                Dim EndDate As Date = Now.ToUniversalTime
                Dim val As Long = DateDiff(DateInterval.Second, StartDate, EndDate)
                Return val
            End Get

        End Property

#End Region

    End Class
    Sub Main()
        Console.WriteLine("Getting token...")
        Dim myif As New myAPIClass()

        Try
            Console.WriteLine("Token received:  " & myif.AccessToken)
            Console.WriteLine("Connecting to SQL Server and inserting authentication token...")
            Dim con As New SqlConnection(ConfigurationManager.AppSettings("ConnectionString"))
            con.Open()
            Dim cmd As New SqlCommand("INSERT INTO MYDB (InsertDate, AuthenticationCode, Length) VALUES ('" & DateTime.Now.ToString() & "', '" & myif.AccessToken & "', 40)", con)
            cmd.ExecuteNonQuery()
            Console.WriteLine("Done!")
        Catch ex As Exception
            Console.WriteLine(ex.Message)
            Console.WriteLine("Resulting Error --- " & ex.Message)
        End Try

    End Sub

End Module

1 个答案:

答案 0 :(得分:0)

您的GetAccessToken方法应如下所示:

Public Sub GetAccessToken()

    System.Net.ServicePointManager.SecurityProtocol = Net.SecurityProtocolType.Tls12

    Dim tokenHttpClient As New HttpClient()
    tokenHttpClient.BaseAddress = New Uri(FullURL)

    Dim HttpRequestMessage As New HttpRequestMessage()
    HttpRequestMessage.Method = HttpMethod.Post
    HttpRequestMessage.Headers.Accept.Add(New MediaTypeWithQualityHeaderValue("application/json"))

    Dim stJWT As String = CreateJWT()

    Dim parameters As New Dictionary(Of String, String)
    parameters.Add("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer")
    parameters.Add("assertion", stJWT)

    Dim encodedContent As New FormUrlEncodedContent(parameters)
    encodedContent.Headers.ContentType = New MediaTypeHeaderValue("application/x-www-form-urlencoded")
    HttpRequestMessage.Content = encodedContent

    Dim response As HttpResponseMessage = tokenHttpClient.SendAsync(HttpRequestMessage).Result

    If response.IsSuccessStatusCode Then
        Dim rawResponseFromServer As String = response.Content.ReadAsStringAsync().Result
        Dim o As JObject = JObject.Parse(rawResponseFromServer)
        Me.AccessToken = o.Item("access_token").Value(Of String)()
    End If
End Sub

请注意,httpClient中使用的所有功能都是异步的。.Result以同步方式强制它,而不必等待它们

我不确定它是否可以解决您的tls问题。您可能需要添加httpClientHandler

Dim httpClientHandler As New HttpClientHandler()
httpClientHandler.SslProtocols = Authentication.SslProtocols.Tls12 Or Authentication.SslProtocols.Tls11
httpClientHandler.ServerCertificateCustomValidationCallback = AddressOf TrustAllCertificatesCallback

tokenHttpClient = New HttpClient(httpClientHandler)    

Private Function TrustAllCertificatesCallback(sender As Object, certificate As System.Security.Cryptography.X509Certificates.X509Certificate, chain As System.Security.Cryptography.X509Certificates.X509Chain, sslPolicyErrors As SslPolicyErrors) As Boolean
    Return True
End Function

属性HttpClientHandler.SslProtocols可在Assembly System.Net.Http版本= 4.2.0.0中找到