Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB.NET: [VB .NET] HttpWebRequest

K_L [29.12.2011 11:04:03]

#

Haen eräältä sivulta tietoa HttpWebRequestilla.
Kirjautuminen tuntuu toimivan hyvin. Ongelmat alkavat haettaessa sivua jossa on kehykset. Itse kehyksillä ei ole mitään tekemistä ongelman kanssa, jos URL on haettu oikein src:stä.

Selaimella voi hakea halutun sivun ilman kehyksiä katsomalla lähdekoodista suora osoite. https://intra.hva.dom/Serv/Dyn/Sup.aspx?maid=8b170d0c-04fe-424c-912a-591fbfb03de5&parentmaid=0c292623-ace1-45b2-bfaa-1c13adc9f5e5&SetFrameTitle=True

 <FRAMESET cols='660,*,0' framespacing='2' frameborder='1'>
      <FRAME src='Dyn/Sup.aspx?maid=8b170d0c-04fe-424c-912a-591fbfb03de5&parentmaid=0c292623-ace1-45b2-bfaa-1c13adc9f5e5&SetFrameTitle=True' name='Left' frameborder='2' bordercolor='#eaeaea' resize='yes' scrolling='auto'>
      <FRAME src='empty.aspx' name='Right' frameborder='2' bordercolor='#eaeaea' resize='yes' scrolling='auto'>
       <FRAME src='empty.aspx' name='HiddenFrame' frameborder='0' bordercolor='#eaeaea' resize='yes' scrolling='no'>
  </FRAMESET>

maid-parametri generoituu joka sessiolle automaattisesti, mutta tuosta kopioimalla saa sivun auki nätisti.
Koodissa luen tuon Frameset-sivun muistiin, ja etsin siitä osoitteen.

 ' frameset URL. Kirajutumisesta on saatu cookie ja maid-parametri
 URL = "https://intra.hva.dom/Serv/WrappedFramesetSub.aspx?HiddenFrame=True&LeftWidth=660&left=Dyn/Sup.aspx " & maid
 'Uusi haku salasanasuojatulle sivulle
 httpReq = CType(WebRequest.Create(URL), HttpWebRequest)
 httpReq.ClientCertificates.Add(certificate)
 'Aiemmin hankittu keksi
 httpReq.CookieContainer = cookie
 httpReq.AllowAutoRedirect = True
 'Luetaan sivu
 httpReq.KeepAlive = True
 'Luetaan sivu
 response = CType(httpReq.GetResponse(), HttpWebResponse)
 Str = New StreamReader(response.GetResponseStream()).ReadToEnd()
 Dim supermaid As String = ExtractMaid(Str ", "Dyn", "'")

 ' Haetaan haluttu tieto
 URL = "https://intra.hva.dom/Serv/" & supermaid
 'Uusi haku salasanasuojatulle sivulle
 httpReq = CType(WebRequest.Create(URL), HttpWebRequest)
 ‘Sivunston vaatima sertti pidetävä mukana
 httpReq.ClientCertificates.Add(certificate)
'Aiemmin kirjautumisesta saatu keksi
 httpReq.CookieContainer = cookie
  'Ilman tätä tulee Object moved
  httpReq.AllowAutoRedirect = True
 'Luetaan sivu
 response = CType(httpReq.GetResponse(), HttpWebResponse)
 Str = New StreamReader(response.GetResponseStream()).ReadToEnd()
 'Tallennetaan sivu
 Console.WriteLine("RequestUri:")
 Console.WriteLine(httpReq.RequestUri)
 Console.WriteLine("ResponseUri:")
 Console.WriteLine(response.ResponseUri)

RequestUri:
https://intra.hva.dom/Serv/Dyn/Sup.aspx?maid=8b170d0c-04fe-424c-912a-591fbfb03de5&parentmaid=0c292623-ace1-45b2-bfaa-1c13adc9f5e5&SetFrameTitle=True
ResponseUri:
https://intra.hva.dom/Serv/MessagePage.aspx?aspxerrorpath=/Serv/Dyn/Sup.aspx

Kuten tuosta näkyy, on Request Uri saanut oikean osoitteen haetusta kehyksestä. Jostain syystä HttpWebRequest silti ohjautuu virhesivulle. En ymmärrä miksi näin tapahtuu tässä, mutta ei manuaalisesti selaimella tehdessä.
Tein koodiin muutoksen, joka hakee etusivun uudelleen epäonnistuneen haun jälkeen. Etusivu tulee edelleen oikein, eli cookie ja maid-parametri ovat edelleen voimassa. Jos RequesteUri:sta ottaa pois maid-parametrin, saa selkeän virheilmoituksen sen puuttumisesta.

Mikä piru tässä nyt mättää?

Grez [29.12.2011 17:29:10]

#

Arvaan että bugisesti koodattu sovellus serverillä heittää evästeen, joka on virheellinen ja cookiecontainer ei hyväksy sitä sen takia. Selaimet yleensä arpovat myös vialliset evästeet käyttöön.

Katso mitä evästeitä palvelin lähettää ja meneekö ne kaikki takaisin. Itse olen törmännyt tähän mm. erään SAPiin tehdyn extranetin kanssa.

Sanotaanko esimerkiksi että seuraava eväste on epävalidi eikä tartu sellaisenaan CookieContaineriin:
Path=/erp2/
JSESSIONID=(J2EE1232323232)IDas299129das3200End; Version=1; Domain=www.firma.fi; path=/

Siinä nimittäin sanotaan että Version=1, mutta Domain ei ala pisteellä. Jos tuon Version=1 määritteen jättäisi pois, niin se olisi validi eväste. Sinänsä jotenkin koomista että ylipäätään pitää ilmoittaa versio, jos ei osaa sitten implementoida sitä oikein.

Sen sijaan selaimet katsoo tuota virhettä sormien läpi.


Tokihan vika voi olla muukin, vaikea sanoa kun ei voi testata.

neau33 [30.12.2011 02:50:58]

#

Moi K_L!

eräs toinen tapa poimia framesetin osoitteet...

'väännetty SharpDevelop 4.0:lla
Imports System
Imports System.Threading
Imports Microsoft.VisualStudio.OLE.Interop
Imports mshtml 'Microsoft.mshtml

Module Program

   'testi URL...
   Private baseUrl As String = _
   "http://www.elisanet.fi/nea.fi/frametest/" 'index.html

   Private objMSHTML As New HTMLDocument
   Private objDocument As IHTMLDocument2
   Private ips As IPersistStreamInit = _
   CType(objMSHTML, IPersistStreamInit)

   Sub Main()

      ips.InitNew
      objDocument = _
      objMSHTML.createDocumentFromUrl(baseUrl, "")

      While objDocument.readyState <> "complete"
         'Huom tuo refernssi System.Windows.Forms
         System.Windows.Forms.Application.DoEvents
         Thread.Sleep(100)
      End While

      Dim theDoc As HTMLDocument = _
      CType(objDocument, HTMLDocument)

      Dim htmlFrames As IHTMLElementCollection = _
      theDoc.getElementsByTagName("frame")

      If htmlFrames.length > 0 Then

         For i As Integer = 0 To htmlFrames.length - 1

            Dim frameNode As IHTMLDOMNode = _
            CType(htmlFrames.item(i),IHTMLDOMNode)
            Dim AttrColl As IHTMLAttributeCollection = _
            CType (frameNode.attributes, IHTMLAttributeCollection)
            Dim frameUrl As String = String.Empty

            For Each objItem As IHTMLDOMAttribute2 In AttrColl
               With objItem
                  If .name = "src" Then
                     If .value.Contains("://") Then
                        frameUrl = .value
                     Else
                        frameUrl = baseUrl + .value 'esim.
                     End If
                     Console.WriteLine(frameUrl)
                  End If
               End With
            Next objItem

            AttrColl = Nothing
            frameNode = Nothing

         Next i

      Else
         Console.WriteLine("Requested page has no frame elements!")
      End If

      htmlFrames = Nothing
      theDoc = Nothing
      ips = Nothing
      objDocument = Nothing
      objMSHTML = Nothing

      Console.Write("Press any key to continue . . . ")
      Console.ReadKey(True)

   End Sub

End Module

K_L [30.12.2011 10:24:10]

#

Nea kokeilen tuota, jos en saa tätä HttpWebRequest:lla toimimaan.

Hain vastauksesta keksit response.Cookies = httpReq.CookieContainer.GetCookies(httpReq.RequestUri)

Istunnossa on niitä kaksi.

Cookies: 2
Cookie Name: ASP.NET_SessionId
Cookie Version: 0
Cookie Value: ....
Cookie Path: /
Cookie Domain: intra.hva.dom
Cookie expires: 12:00:00 AM

Cookie Name: adAuthCookie
Cookie Version: 0
Cookie Value: .....
Cookie Path: /
Cookie Domain: intra.hva.dom
Cookie expires: 12:00:00 AM

Nämä keksit ovat jokaisessa haussa mukana. http://www.codeproject.com/Articles/49243/Handling-Cookies-with-Redirects-and-HttpWebRequest Tämä saattaa ratkaista ongelman, mutta toisaalta mitään uudelleenohjausta ei pitäisi tapahtua.

Tutkin sivun avaamista FF:n tamper data lisäplugin avulla. Siinä ei ilmennyt mitään uutta. Alustava testi Selenium IDE:lltä tyssäsi menuvalikkoon.

neau33 [31.12.2011 02:06:18]

#

Moi taas K_L!

testaa oheista viritelmää...

'ConsoleApp
Imports System.IO
Imports System.Text
Imports System.Net

Module Program

   Private baseURL As String = _
   "http://aspspider.net/neoweb/Serv/"

   Sub Main()

      Dim request As HttpWebRequest = _
      CType(WebRequest.Create(baseURL + _
      "WrappedFramesetSub.aspx"), HttpWebRequest)

      Dim response As HttpWebResponse = _
      CType(request.GetResponse(), System.Net.HttpWebResponse)

      Dim content As String = _
      New StreamReader(response.GetResponseStream()).ReadToEnd()
      response.Close()

      If content.ToUpper.Contains("FRAMESET") Then

         Dim strArray() As String = content.Split(CType("'", Char))
         Dim frameURL As String = String.Empty

         For i As Integer = 0 To strArray.Length -1
            If strArray(i).Contains("Dyn/") Then
               If strArray(i).Contains("://") Then
                  frameURL = strArray(i)
               Else
                  frameURL = baseURL + strArray(i)
               End If
               Exit For
            End If
         Next

         If frameURL = String.Empty
	    Console.WriteLine("No matching found")
            GoTo ExitProg
         End If

         Dim cookies As CookieContainer = New CookieContainer

         request = _
         CType(WebRequest.Create(frameURL), HttpWebRequest)

         Dim postData As String = "terve=moro&moro=terve"

         request.UserAgent = _
         "Mozilla/5.0 (Windows; U; Windows NT 5.1; fi; rv:1.9.0.5) " _
         + "Gecko/2008120122 Firefox/3.0.5 (.NET CLR 3.5.30729)"
         request.Method = "POST"
         request.AllowAutoRedirect = True
         request.ContentType = "application/x-www-form-urlencoded"
         request.CookieContainer = cookies
         request.ContentLength = postData.Length

         Dim requestStream As Stream = request.GetRequestStream()

         Dim postBytes As Byte() = _
         Encoding.Default.GetBytes(postData)
         requestStream.Write(postBytes, 0, postBytes.Length)
         requestStream.Close()
	 postBytes = Nothing
	 cookies = Nothing

         response = _
         CType(request.GetResponse(), HttpWebResponse)
         response.Close

         For Each item As Cookie In response.Cookies
            With item
               If .Name = "location" Then
                  Console.WriteLine(.Value): Exit For
               End If
            End With
         Next

      Else
         Console.WriteLine("Requested page has no frames")
      End If

ExitProg:

      response = Nothing
      request = Nothing
      Console.Write("Press any key to continue . . . ")
      Console.ReadKey(True)

   End Sub

End Module
<%@ Page Language="VB"%>
<%@ Import Namespace="System.Web" %>