HTTP_GET - mit Authorization Basic

Begonnen von neutrino2k, 23. Februar 2013, 18:25:51

Vorheriges Thema - Nächstes Thema

0 Mitglieder und 2 Gäste betrachten dieses Thema.

neutrino2k

Hallo,

ich habe einen Vorschlag für eine Erweiterung des HTTP_GET.
Hatte selbst gerade das Problem, dass ich einen Webinterface mit Authorization Basic, spricht Base64 verschlüsselt, abfragen wollte.
Mit dem original HTTP_GET bekam ich immer "401 Unauthorized", obwohl ich den Benutzernammen und Passwort im URL hatte.
Also hab ich im HTTP_GET geschaut, wo der Header zusammen gesetzt wird und hab ihn um folgende Zeile ergänzt:

VAR_INPUT
AUTHORIZATION
END_VAR

text := CONCAT(text,URL_DATA.HEADER);
_STRING_TO_BUFFER(STR:=text,POS:=idx,PT:=ADR(S_BUF.BUFFER),SIZE:=SIZEOF(S_BUF.BUFFER)); (* HTTP Version in buffer kopieren *)
idx := idx + LEN(text);

   text:=CONCAT('Authorization: Basic ', AUTHORIZATION);
   text := CONCAT(text,delimiter4b);
   _STRING_TO_BUFFER(STR:=text,POS:=idx,PT:=ADR(S_BUF.BUFFER),SIZE:=SIZEOF(S_BUF.BUFFER)); (* HTTP Authorization in buffer kopieren *)
   idx := idx + LEN(text);
      
text := CONCAT('Host: ',URL_DATA.DOMAIN);
text := CONCAT(text,delimiter4b); (* workaround für pcworx -> kein $0D$0A als Stringkonstante möglich *)
_STRING_TO_BUFFER(STR:=text,POS:=idx,PT:=ADR(S_BUF.BUFFER),SIZE:=SIZEOF(S_BUF.BUFFER)); (* HTTP Host in buffer kopieren *)
idx := idx + LEN(text);



Man könnte das Ganze noch mit einem boolschen Eingang am HTTP_GET aktivieren/deaktivieren.
Habe dann noch den BASE64_ENCODE_STR vor den Eingang AUTHORIZATION am HTTP_GET gesetzt. Diesen könnte man auch fest integrieren.

peewit

hallo neutrino2k

danke für deine idee und lösung

ich werde es auf meine ToDo liste setzen....

peter.haider

Guten Abend,
leider habe ich selbiges Problem mit dem Fehler 401 Unauthorized.

In der oscat_network_121 für PC-Worx ist die oben genannte Lösung nicht umgesetzt.
Auch die oscat_network_130 aus dem Forum beinhaltet keine Authentifizierung mittels User und Passwort.
Nach vergeblicher Mühe der Implementierung bitte ich um Hilfe bei der Integration in den HTTP_GET Baustein der oscat_network_121 oder um einen funktionierenden Baustein.

Besten Dank im Voraus,
Peter

peter.haider

Also, die Athentifizierung funktioniert nun soweit(siehe unten)
Nur erkennt der Baustein kein "DONE", obwohl im R_BUF.BUFFER "1.1 200 OK" steht(Ausserhalb des Bausteins abgefragt).
Scheinbar ein Problem von BUFFER_SEARCH in Step 30.
Deaktiviere ich die User Authentication, der Fehler 401 tritt auf, dann ermittelt die Suche eine del_pos von 139!

Bitte um Hilfe



(* -------------------------------------------------------------------------*)
      text := CONCAT(text,URL_DATA.HEADER);
      _STRING_TO_BUFFER(STR:=text,POS:=idx,PT:=S_BUF.BUFFER,SIZE:=UINT#4096); (* HTTP Version in buffer kopieren *)
      S_BUF.BUFFER:=_STRING_TO_BUFFER.pt;
      idx := idx + LEN(text);
(* -------------------------------------------------------------------------*)
(* Authorization-Header in der Form Benutzername:Passwort Base64-codiert    *)
(* -------------------------------------------------------------------------*)
      user_pwd := CONCAT(URL_DATA.USER,':');
      user_pwd := CONCAT(user_pwd,URL_DATA.PASSWORD);
(* -------------------------------------------------------------------------*)
      BASE64_ENCODE_STR_1(RUN:=USER_PWD_ACTIVE,STR1:=user_pwd,STR2:=user_pwd_base64);
      user_pwd:=BASE64_ENCODE_STR_1.STR1;
      user_pwd_base64:=BASE64_ENCODE_STR_1.STR2;
(* -------------------------------------------------------------------------*)
(*               HTTP Authorization in buffer kopieren *)
(* -------------------------------------------------------------------------*)
      IF USER_PWD_ACTIVE THEN
         text:=CONCAT('Authorization: Basic ', user_pwd_base64);
         text := CONCAT(text,delimiter4b);
            _STRING_TO_BUFFER(STR:=text,POS:=idx,PT:=S_BUF.BUFFER,SIZE:=UINT#4096);    
            S_BUF.BUFFER:=_STRING_TO_BUFFER.pt;
         idx := idx + LEN(text);
      END_IF;
(* -------------------------------------------------------------------------*)
      text := CONCAT('Host: ',URL_DATA.DOMAIN);
      text := CONCAT(text,delimiter4b); (* workaround für pcworx -> kein $0D$0A als Stringkonstante möglich *)
      _STRING_TO_BUFFER(STR:=text,POS:=idx,PT:=S_BUF.BUFFER,SIZE:=UINT#4096); (* HTTP Host in buffer kopieren *)
      S_BUF.BUFFER:=_STRING_TO_BUFFER.pt;
      idx := idx + LEN(text);
(* -------------------------------------------------------------------------1,221*

peewit

hi

mach mal eine wireshark aufzeichung davon (mit Authorization)

dann kann ich sehen was im detail hin und her geschickt wird und sehr schnell erkennen was noch falsch läuft !


peter.haider

Nachdem der Switch mit Portspiegelung geliefert wurde siehe Anhänge.

172.20.10.11   = Phoenix SPS mit HTTP_Get Baustein
172.20.10.254 = Router
172.20.3.0       = PC mit funktionierender Firefox Anfrage(Browser Meldung "SMS send done")

Besten Dank,
Peter

[gelöscht durch Administrator]

peewit

hi

du musst schon das ganze file hergeben
der dem bild kann man nicht das problem lösen !

empfehlung
ändere den zugangscode vorher dem aufzeichnen oder nacher ... wie du willst
dann brauchst du keine angst haben das jemand deinen zugriffcode hat !

peter.haider

Hier die beiden Dateien, sind sowieso nur Testdaten...

[gelöscht durch Administrator]

peewit

hallo

hab mir das mal kurz angesehen

es passiert normalerweise folgendes

1. deine parameter werden an den server übermittelt
2. der server schickt dann den http header (200 OK) als antwort
3. dann dauert es ca. 2 sekunden bis dein server die arbeit erledigt hat und schickt nachträglich eine html-seite als bestätigung


das der header und die body daten zweigeteilt sind und mit 2 sekunden abstand folgen ist das jetzige problem

der http_get baustein denkt nach der ersten antwort das alles erledigt ist und beendet die verbindung , da er ja nicht ahnen kann das noch etwas folgt.

allerdings hast du beim hhtp_get baustein auch den http1.0 modus vorgegeben und der server antwortet mit http 1.1
das ergibt wahrscheinlich auch das grundproblem

du solltest also beim http_get baustein auf mode 3 umstellen
und beim ip_control.timeout mindestens 4-5 sekunden

dann sollte normalerweise header und body bei der sps ankommen und nach timeout (5 sekunden) wird die übertragung als beendet angesehen und dann so hoffe ich sollte es auch funktionieren


ändere mal dein programm und mache wieder einen wireshark mitschnitt
wenn es noch nicht funktioniert stelle den mitschnitt wieder online
dann werde ich nochmals nachbessern

mfg peewit


peter.haider

#9
Hat leider nicht geklappt mit Mode byte#3 und ip_control.timeout von 5s

[gelöscht durch Administrator]

peewit

#10
hi

so wie es aussieht wird zwischen header und body eine trennmarkierung verwendet die ich nicht vorgesehen habe

abgefragt wird bisher     $D$A$D$A   oder  $A$A     aber kein $D$A

öffne die lib als projekt und ergänze den code vom http_get wie dargestellt
siehe neuen block mit (neu  neu ) kommentar


(* kein Ende gefunden ? -> andere Ende-Codierung suchen *)
IF del_pos = 0 THEN
          (* workaround für pcworx -> kein $0A$0A als Stringkonstante möglich *)
          del_end := CONCAT(BYTE_TO_STRING(BYTE#16#0A,'%c'),BYTE_TO_STRING(BYTE#16#0A,'%c'));

          (* HTTP HEADER Ende suchen -> durch $A$A erkennbar bei Multics, Unix-Derivate,Mac OS X *)
          BUFFER_SEARCH(size:=R_BUF.SIZE,str:=del_end,pos:=0,ign:=FALSE,pt:=R_BUF.BUFFER);
          R_BUF.BUFFER:=BUFFER_SEARCH.pt;
  del_pos := BUFFER_SEARCH.BUFFER_SEARCH;
        END_IF;

(* NEU NEU NEU      kein Ende gefunden ? -> andere Ende-Codierung suchen *)
IF del_pos = 0 THEN
          (* HTTP HEADER Ende suchen -> $0D$0A *)
          BUFFER_SEARCH(size:=R_BUF.SIZE,str:=delimiter2b,pos:=0,ign:=FALSE,pt:=R_BUF.BUFFER);
          R_BUF.BUFFER:=BUFFER_SEARCH.pt;
  del_pos := BUFFER_SEARCH.BUFFER_SEARCH;
        END_IF;

IF del_pos > 0 THEN
HEADER_START := UINT#0;
HEADER_STOP  := INT_TO_UINT(del_pos + LEN(del_end) - 1);
TOTAL_SIZE   := -1; (* HTTP Header empfangen aber noch keine gesamtlänge bekannt *)
END_IF;


peter.haider

So wie du es beschrieben hast funktionierte es nicht.
Ich habe aber einfach deinen Code wieder entfernt und del_end auf delimiter2b gesetzt:
(* HTTP HEADER Ende suchen -> durch $0D$A$0D$A erkennbar bei DEC RT-11,CP/M,MS-DOS,Windows *)
del_end := delimiter2b;


Jetzt bekomme ich ein Done vom Baustein.
Soll ich die Zuweisung auf "del_end" so belassen?

Und, wie du schon erkannt hast, bekomme ich eine Meldung in Form einer Webseite zum Status des SMS Versands.
Da ich eine Simkarte ohne Telefonie Guthaben zum testen verwendete, kam die Meldung" SMS sending failed"
Jetzt sollte ich das unabhängig vom Done noch zusätzlich überwachen.
Wie können wir den Inhalt der nachträglich gesendeten Webseite auf "failed" oder "successfully sent" überprüfen, bzw in eine Variable schreiben?

Besten Dank im Voraus

[gelöscht durch Administrator]

peewit

#12
hi

irgendwo hatte ich wahrscheinlich einen kleinen fehler
die idee war aber zum glück die richtige


da du nun die antwortdaten korrekt empfangen kannst sollte der rest kein riesen problem sein

der baustein gibt dir bei "BODY_START" und "BODY_STOP" an wo bis wo sich die BODY Daten im R_BUFFER befinden

folgenden markanten text gibt es

"SMS successfully sent"   und      "SMS sending failed"

sobald die antwortdaten im buffer stehen benutzt den den baustein "BUFFER_SEARCH"
um genau von start bis stop position nach den TEXT "SMS successfully sent" zu suchen
findest du den text nicht dann gab es ein problem ansonsten ok

wie man den buffer_search anwendet kannst du im http_get baustein selber dir auch ansehen


mach doch nochmals eine wireshark-aufzeichnung mit der jetzigen version wo die kompletten daten ankommen und wo die negative antowrt vorkommt



folgend siehst du den body_daten text der als antwort kommt (eine echte html-seite)


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>UR5i-v2</title>
<style type="text/css">
<!--
body, table, tr, td, a {
  font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif;
}
form, input {
  margin: 0px;
}
pre {
  margin: 10px 0px 10px 0px;
}
h2 {
  font-size: 24px; margin-bottom: 3px;
}
a {
  color: #0033CC; text-decoration: none;
}
a:hover {
  text-decoration: underline;
}
.logo {
  color: #000080; text-shadow: #B0C0E0 2px 2px 2px; filter: shadow(color=#B0C0E0, direction=145, strength=4);
}
.window {
  background-color: #F4F4F4;
}
.title {
  color: #FFFFFF; background-color: #000080; border-color: #000080; font-weight: bold;
}
.header {
  color: #000000; background-color: #C8D8FF;
}
.input {
  width: 165px;
}
-->
</style>
</head>

<body bgcolor="#FFFFFF">
<center>
<form name="f" action="">
<table cellspacing="0" cellpadding="5" border="3" class="window">
  <tr>
    <td bgcolor="#008000" align="center"><font color="#FFFFFF"><b>Send SMS</b></font></td>
  </tr>
  <tr>
    <td>
      <table>
        <tr align="center">
          <td>SMS successfully sent.</td>
        </tr>
        <tr align="center">
          <td id="button"><a href="send.cgi">&raquo; Back &laquo;</a></td>
        </tr>
      </table>
    </td>
  </tr>
</table>
</form>
</center>
<script type="text/javascript">
<!--
document.getElementById('button').innerHTML = '<input type="button" name="button" value="Back" onclick="location.href=\'send.cgi\'">';
document.f.button.focus();
//-->
</script>
</body>

</html>


peter.haider

So, nun bekomme ich den Suchstring, wenn im HTML Body vorhanden, als Ausgabe.
Ein Vergleich der beiden außerhalb des Bausteins ermöglicht mir in Kombination mit "DONE" ein sicheres erkennen ob die SMS versendet wurde.

[/
DONE := TRUE;
IP_C.C_ENABLE := FALSE; (* Verbindung abbauen  *)

(* ------------------------------   Body Daten auf SMS Versand-Bestätigung durchsuchen   -----------------------------------------*)
                IF BODY_START > UINT#0 THEN
BUFFER_SEARCH_1(SIZE:=R_BUF.SIZE,STR:=SEARCH_BODY_STRING,POS:=UINT_TO_INT(BODY_START),IGN:=FALSE,PT:=R_BUF.BUFFER);
R_BUF.BUFFER:=BUFFER_SEARCH_1.PT;
search_string_startpos:=BUFFER_SEARCH_1.BUFFER_SEARCH;
ELSE
search_string_startpos:=-1;
END_IF;

IF search_string_startpos > -1 THEN
BUFFER_TO_STRING_NW_1(PT:=R_BUF.BUFFER,SIZE:=R_BUF.SIZE,START:=INT_TO_UINT(search_string_startpos),STOP:=INT_TO_UINT(search_string_startpos) + INT_TO_UINT(len(SEARCH_BODY_STRING)-1));
R_BUF.BUFFER:=BUFFER_TO_STRING_NW_1.PT;
BODY_STRING:=BUFFER_TO_STRING_NW_1.BUFFER_TO_STRING;
ELSE
BODY_STRING:='Keine Übereinstimmung';
END_IF;
(* -------------------------------------------------------------------------------------------------------------------------------*)code]


Anbei noch die Wireshark Datei mit negativer Antwort "SMS sending failed".

@ peewit: Besten Dank für deine Zeit!

PS: im HTTP_Get Baustein sind einige Warnungen in PCWorx gemeldet worden, da diverse Baustein Aufrufinstanzen mehrmals verwendet werden.(zb:_STRING_TO_BUFFER)
      Die habe ich bereinigt. Das sollte bei vielen OSCAT Bausteinen erledigt werden...


[gelöscht durch Administrator]

peewit

#14
hi

thema:
PS: im HTTP_Get Baustein sind einige Warnungen in PCWorx gemeldet worden, da diverse Baustein Aufrufinstanzen mehrmals verwendet werden.(zb:_STRING_TO_BUFFER)
      Die habe ich bereinigt. Das sollte bei vielen OSCAT Bausteinen erledigt werden...


bei pcworx ist es manchmal notwendig einen fb statt einer function zu verwenden obwohl es technisch keinen grund gibt
da bei einen fb immer pro instanz speicher belegt wird, verwende ich absichtlich immer die gleiche instanz

da die fb's aber sich nichts merken müssen ist es kein problem
die meldung kannst du ignorieren und ist in dem fall bewusst in kauf genommen worden
jeden fb aufruf mit einer eigenen instanz aus zustatten belegt in dem fall unnütz speicher

im original ist ja der buffer_search eine function aber so nicht in pcworx umsetzbar

aber du kannst es natürlich so machen , denk nur dran das mehr speicher verbraten wird.