【问题标题】:Convert legacy HttpWebRequest POST to HttpClient async POST class (VB)将旧版 HttpWebRequest POST 转换为 HttpClient 异步 POST 类 (VB)
【发布时间】:2019-11-28 17:00:55
【问题描述】:

我有一个 .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? GetAccessToken 方法是 HttpWebRequest 的问题所在。

感谢任何帮助!

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

【问题讨论】:

    标签: .net httpwebrequest httpclient


    【解决方案1】:

    您的 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-05
      • 1970-01-01
      • 2018-05-20
      • 2021-02-14
      • 2010-10-20
      相关资源
      最近更新 更多