所有.tv域名的.net 4.61 httpwebrequest失败,尤其是https://www.tvone.tv

时间:2018-01-17 22:25:33

标签: vb.net httpwebrequest

我正在使用.net 4.61并在https://www.tvone.tv上使用VB执行httpwebrequest,并且每次都无法连接到服务器。除.tv之外的任何其他域上的任何其他查找都可以正常工作。我得http://ustream.tv只工作一次,但只有一次而且再也没有。

这是一个.net问题还是.net的dns问题?

IE,Edge,Firefox和Chrome都可以从我用来编译的计算机上加载网页。所以,我知道这不是一个网络问题。

我是否需要使用httpwebrequests加载.tv域的特定方式?

1 个答案:

答案 0 :(得分:1)

您提到的其中一个网站在URI中有Https:架构 这意味着使用了安全协议。经检查,该站点使用TLS 1.2安全协议。因此,您必须使用ServicePointManager启用它,设置为:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

此外,大多数情况下,网站使用Cookie(或 使用Cookie,因为外部资源需要它们。例如,Google工具)。
您必须提供接受,存储和交换它们的方法 这是完成实例化CookieContainer Object并使用其HttpWebRequest将其传递给.CookieContainer() Property

<小时/> 所以我测试了所有这些,看看幕后发生了什么(见结果)
其中一个比其他人更有趣(https://www.tvone.tv)。它是不接受Https:之外的其他模式的其中一个。如果您更改它,它会将您的请求重定向回它(通过Tls 1.2证书交换强制安全性)。但它(至少是主页)不使用cookies 由于我认为它有点有趣,我发布了用于测试的代码。如果在“页眉”设置中设置了.AllowAutoRedirect = False,则可以按照重定向查看其功能。

  

主机URI:https://tvone.tv/
  IP地址:45.79.161.20
  响应状态:OK Http协议:Http / 1.1
  Cookies n°:0安全协议:Tls 1.2

     

使用Https:架构尝试此操作   主机URI:http://www.ustream.tv/
IP地址:199.66.238.212
  响应状态:OK Http协议:Http / 1.1
   Cookies n°:2安全协议:N / A

     

主机URI:http://www.fyi.tv/
  IP地址:151.101.14.168
  响应状态:OK Http协议:Http / 1.1
  Cookies n°:1安全协议:N / A
  

这是用于测试的代码 (它是我的图书馆的编辑/翻译版本,因此如果你使用它,你不必担心踩到任何人的脚趾。)

主函数HTTP_GetWebPageAsync()可以这样调用:
(返回的对象返回时其属性填充了上面结果中显示的数据,加上响应的整个Html页面(在Public Property PayLoad中)。)

Public HttpReqObject As HttpReqObj = New HttpReqObj

Dim MaxWaitTimeOut As Integer = 30  'Seconds
HttpReqObject.SiteURL = "https://tvone.tv/"
HttpReqObject = Await HTTP_GetWebPageAsync(HttpReqObject, MaxWaitTimeOut)


Imports System.IO
Imports System.Net
Imports System.Net.Security
Imports System.Reflection
Imports System.Security
Imports System.Security.Authentication
Imports System.Security.Cryptography.X509Certificates
Imports System.Text

Private Const COR_E_INVALIDOPERATION As Int32 = &H80131509

Public Class HttpReqObj
    Public Property SiteURL As String
    Public Property StatusCode As HttpStatusCode
    Public Property PayLoad As String
    Public Property Cookies As CookieContainer
    Public Property HostAddress As IPAddress()
    Public Property HttpProtocol As String
    Public Property SslProtocol As SslProtocols
End Class

Public Async Function HTTP_GetWebPageAsync(HttpSite As HttpReqObj, ReqTimeOut As Integer) As Task(Of HttpReqObj)
    Dim _HttpRequest As HttpWebRequest
    Dim _Cookiejar As New CookieContainer()
    Dim _StatusCode As HttpStatusCode
    Dim _RedirectURL As String = String.Empty
    Dim _Referer As String = String.Empty
    Dim _Payload As String = String.Empty
    Dim _MaxAwaitableTimeout As Integer = ReqTimeOut
    Dim _MaxHops As Integer = 40

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 Or
                                           SecurityProtocolType.Tls11 Or
                                           SecurityProtocolType.Tls12
    ServicePointManager.ServerCertificateValidationCallback = AddressOf TlsValidationCallback

    Try
        _HttpRequest = WebRequest.CreateHttp(HttpSite.SiteURL)
        HttpSite.HostAddress = Await Dns.GetHostAddressesAsync(_HttpRequest.Host)
        HTTP_RequestHeadersInit(_HttpRequest, _Cookiejar, "")
        _HttpRequest.Method = WebRequestMethods.Http.Get
        Using httpResponse As HttpWebResponse = CType(Await _HttpRequest.GetResponseAsync(), 
                                                            HttpWebResponse)
            _StatusCode = httpResponse.StatusCode
            _Payload = If(_StatusCode = HttpStatusCode.OK, ProcessResponse(httpResponse, HttpSite), String.Empty)
            _RedirectURL = URIFromResponseLocation(httpResponse).ToString()
            HttpSite.HttpProtocol = "Http/" + _HttpRequest.ProtocolVersion.ToString()
        End Using


        'On Page Redirection, follow redirections [_MaxHops] hops and [_MaxAwaitableTimeout] time
        If (_RedirectURL <> HttpSite.SiteURL) Or (_StatusCode = HttpStatusCode.Moved) OrElse
                                                 (_StatusCode = HttpStatusCode.Found) OrElse
                                                 (_StatusCode = HttpStatusCode.RedirectMethod) Then

               If (_RedirectURL <> HttpSite.SiteURL) Then
                   Dim _SW As Stopwatch = New Stopwatch()
                   _SW.Start()

                   _Referer = HttpSite.SiteURL
                   HttpSite.SiteURL = _RedirectURL
                   _HttpRequest = WebRequest.CreateHttp(HttpSite.SiteURL)
                   _HttpRequest.Method = WebRequestMethods.Http.Get
                   HTTP_RequestHeadersInit(_HttpRequest, _Cookiejar, _Referer)

                   Dim _hops As Integer = 1
                   Do
                        Using httpResponse As HttpWebResponse = CType(Await _HttpRequest.GetResponseAsync(), 
                                                                            HttpWebResponse)
                            _Payload = ProcessResponse(httpResponse, HttpSite)
                            _StatusCode = httpResponse.StatusCode
                            _RedirectURL = URIFromResponseLocation(httpResponse).ToString()
                        End Using

                        If _RedirectURL <> HttpSite.SiteURL Then
                            If (_StatusCode = HttpStatusCode.Moved) OrElse
                               (_StatusCode = HttpStatusCode.Found) OrElse
                               (_StatusCode = HttpStatusCode.RedirectMethod) Then

                                HttpSite.SiteURL = _RedirectURL
                                _HttpRequest = WebRequest.CreateHttp(HttpSite.SiteURL)
                                HTTP_RequestHeadersInit(_HttpRequest, _Cookiejar, _Referer)
                                _hops += 1
                            End If
                        End If

                        If _SW.Elapsed.Seconds > _MaxAwaitableTimeout Then
                            _StatusCode = HttpStatusCode.RequestTimeout
                            Exit Do
                        End If

                   Loop While (_StatusCode <> HttpStatusCode.OK) AndAlso (_hops < _MaxHops)
                _SW.Stop()
                End If
       End If


    Catch exW As WebException
        _StatusCode = If(exW.Response IsNot Nothing, CType(exW.Response, HttpWebResponse).StatusCode,
                                                     CType(exW.Status, HttpStatusCode))
        _Payload = String.Empty
    Catch exS As System.Exception
        If exS.HResult = COR_E_INVALIDOPERATION Then
            '_StatusCode = If(InternetConnection() > 0, CType(WebExceptionStatus.NameResolutionFailure, HttpStatusCode),
            '                                           CType(WebExceptionStatus.ConnectFailure, HttpStatusCode))
            _StatusCode = CType(WebExceptionStatus.ConnectFailure, HttpStatusCode)
        Else
            _StatusCode = CType(WebExceptionStatus.RequestCanceled, HttpStatusCode)
        End If

        _Payload = String.Empty
    Finally
        ServicePointManager.ServerCertificateValidationCallback = Nothing
    End Try

    HttpSite.Cookies = _Cookiejar
    HttpSite.PayLoad = _Payload
    HttpSite.StatusCode = _StatusCode

    Return HttpSite

End Function


Private Function TlsValidationCallback(sender As Object, CACert As X509Certificate, CAChain As X509Chain, ssl_PolicyErrors As SslPolicyErrors) As Boolean

    If ssl_PolicyErrors = SslPolicyErrors.None Then
        Return True
    End If

    Dim _Certificate As New X509Certificate2(CACert)
    'Dim _CACert As New X509Certificate2("./ca.cert")  'Add your certificate here
    'CAChain.ChainPolicy.ExtraStore.Add(_CACert)
    CAChain.Build(_Certificate)
    For Each CACStatus As X509ChainStatus In CAChain.ChainStatus
        If (CACStatus.Status <> X509ChainStatusFlags.NoError) And
           (CACStatus.Status <> X509ChainStatusFlags.UntrustedRoot) Then
            Return False
        End If
    Next
    Return True
End Function

Private Function ExtractSslProtocol(stream As Stream) As SslProtocols
    Dim bindingFlags__1 As BindingFlags = BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Static

    Dim _objConnection = stream.[GetType]().GetField("m_Connection", bindingFlags__1).GetValue(stream)
    Dim _objTlsStream = _objConnection.[GetType]().GetProperty("NetworkStream", bindingFlags__1).GetValue(_objConnection)
    Dim _objSslState = _objTlsStream.[GetType]().GetField("m_Worker", bindingFlags__1).GetValue(_objTlsStream)
    Return CType(_objSslState.[GetType]().GetProperty("SslProtocol", bindingFlags__1).GetValue(_objSslState), SslProtocols)
End Function


Private Sub HTTP_RequestHeadersInit(ByRef HttpReq As HttpWebRequest, CookieJar As CookieContainer, Referer As String)

    HttpReq.ServicePoint.MaxIdleTime = 30000
    HttpReq.ServicePoint.Expect100Continue = False
    HttpReq.Timeout = 30000
    HttpReq.CookieContainer = CookieJar
    HttpReq.KeepAlive = True
    HttpReq.AllowAutoRedirect = False
    HttpReq.AutomaticDecompression = DecompressionMethods.GZip Or DecompressionMethods.Deflate
    HttpReq.Referer = Referer
    HttpReq.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0"
    HttpReq.Accept = "ext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
    HttpReq.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-US;q=0.8,en;q=0.5")
    HttpReq.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8")
    HttpReq.Headers.Add(HttpRequestHeader.CacheControl, "max-age=0")

End Sub

Private Function ProcessResponse(Response As HttpWebResponse, HttpSite As HttpReqObj) As String

    Dim _html As String
    Dim _encoding As Encoding

    Try
        _encoding = If(Response.CharacterSet.Length > 0,
                       Encoding.GetEncoding(Response.CharacterSet),
                       Encoding.GetEncoding("utf-8"))

        Using _stream As Stream = Response.GetResponseStream()
        HttpSite.SslProtocol = ExtractSslProtocol(_stream)
            Using _memStream As New MemoryStream()
                If Response.ContentEncoding.ToLower().Contains("gzip") Then
                    Using _gzipStream As New Compression.GZipStream(_stream,
                                             Compression.CompressionMode.Decompress)
                         _gzipStream.CopyTo(_memStream)
                    End Using
                ElseIf Response.ContentEncoding.ToLower().Contains("deflate") Then
                    Using _deflStream As New Compression.DeflateStream(_stream,
                                             Compression.CompressionMode.Decompress)
                         _deflStream.CopyTo(_memStream)
                    End Using
                Else
                    _stream.CopyTo(_memStream)
                End If

                _memStream.Position = 0
                Using _reader As New StreamReader(_memStream, _encoding)
                    _html = _reader.ReadToEnd().Trim()
                End Using
            End Using

        End Using
    Catch _Ex As Exception
        Return String.Empty
    End Try

    Return _html

End Function

Private Function URIFromResponseLocation(RefResponse As HttpWebResponse) As System.Uri
    Dim _uri As System.Uri
    Dim _location As String = RefResponse.Headers("Location")

    Try
        If Uri.IsWellFormedUriString(_location, UriKind.Absolute) Then
            _uri = New Uri(_location, UriKind.Absolute)
        Else
            Dim _host_uri As String = RefResponse.ResponseUri.GetComponents(UriComponents.SchemeAndServer,
                                                                            UriFormat.Unescaped) + _location
            If Uri.IsWellFormedUriString(_host_uri, UriKind.Absolute) Then
                _uri = New Uri(_host_uri)
            Else
                _uri = New Uri(RefResponse.ResponseUri.GetComponents(UriComponents.Scheme,
                                                                     UriFormat.Unescaped) +
                                                                     RefResponse.ResponseUri.Host + _location)
            End If
        End If
    Catch _Ex As Exception
        _uri = New Uri(_location, UriKind.Relative)
    End Try

    Return _uri

End Function