Seite 1 von 2

WSDL: Session-ID mit PHP nutzen?

Verfasst: 12.11.2012, 16:50
von Business-Experte
Hallo,

ich setze mich gerade erstmals mit dem Thema passwortgeschützte WSDL auseinander.
Also... Ich habe da eine URL und ein WSDL.

Ich nutze den in PHP eingebauten SoapClient.
Damit rufe ich nun die login-Operation auf, mit User, Domain und Passwort als Parameter.
Im Ergebnis erhalte ich dann eine SessionId und ein SessionTimeout.

So, wenn ich nun weitere Operationen nutzen will, erhalte ich "Permission Denied". Weil: Ich muss dem Webservice ja sicher irgendwie meine SessionId vorzeigen?

Aber wie und wo?
In der Parameterliste der anderen Operationen steht nichts von einer SessionId.

Wie zeige ich dem Webservice meine SessionId?

Verfasst:
von

Verfasst: 13.11.2012, 19:16
von Melegrian
Eine gute Frage und bisher möchte keiner auf die Frage eingehen?

Ich kenne mich nur mit den Sessions aus, die sich mit session_start() erzeugen lassen. Und wenn die Seite abc1.php die Session erzeugt hat, wird auf der Seite abc2.php abgefragt, ob die Session mit den gesetzten Parameter-Werte-Paaren existiert, wobei die Daten von der Session in einem Sessions Cookie gespeichert werden und bei GET oder POST mit der PHPSESSID im HTTP-Header übertragen werden.

Nun ist ja das bei Dir etwas anders, Deine Anwendung bekommt eine Session zugewiesen. Sollte die nicht ebenfalls im Header bei Request und Response übermitteln werden? Meine Scripts liegen ja nun bei mir auf dem Server und der unterhält sich ja nur mit den Clienten.

Nun kann das Unfug sein, was ich schreibe, doch wenn Dein Script, welches auf Deinem Server liegt, nun aber von einem anderen Server eine Session zugeteilt bekommt, die nimmt ja Dein Server nicht an. Somit müsstest Du eventuell den Response-Header auslesen und im Request-Header wieder mit senden oder so. War nur laut gedacht, könnte auch Unfug sein und sich völlig anders verhalten.

Hier steht schon mal etwas:
6.3 SOAP Binding of sessionID
https://www.ecma-international.org/publ ... MA-366.pdf

Mit SOAP habe ich auch noch nichts zu tun gehabt, doch wenn ich mir die Beispiele ansehe, dann könnte das etwa so aussehen:

Code: Alles auswählen

        <SessionHeader>
            <sessionId>8789364113604871127</sessionId>
        </SessionHeader>
https://php.net/manual/de/ref.soap.php

Verfasst: 13.11.2012, 22:01
von Business-Experte
Ja, genau! Ich bin ja der Client und nicht der Server.
Ich habe zwischenzeitlich schon hier ein passendes Beispiel herausgesucht:
https://www.php.net/manual/de/ref.soap.php#83028

Aber dafür bin ich nun nicht mehr wach genug. Hebe ich mir für morgen auf.
Deinen Hinweis werde ich mir auch noch durchlesen, danke!

Man hats nicht leicht, aber leicht hats einen... Hat mein Opa immer gesagt.

Verfasst:
von
SEO Consulting bei ABAKUS Internet Marketing
Erfahrung seit 2002
  • persönliche Betreuung
  • individuelle Beratung
  • kompetente Umsetzung

Jetzt anfragen: 0511 / 300325-0.


Verfasst: 14.11.2012, 08:06
von nerd
verstehe ich nicht. was genau ist denn dein WSDL, oder welchen diesnt willst du denn nutzen?
Laut Wikipedia ist WSDL Ja auch nur ein XML format.
Die session_id wirst du wahrscheinlich an die request_ul anhaengen muessen; also wsd_service.net/api.php?session_id=1234567890 ... oder so aehnlich... schaetze ich mal ohne sein problem genau erraten zu koennen.

Verfasst: 14.11.2012, 11:59
von Melegrian
nerd hat geschrieben:Laut Wikipedia ist WSDL Ja auch nur ein XML format.
Dachte ich bis gestern auch noch. Speichere zum Beispiel die XML von Amazon stundenweise zwischen, da ja eine "normale" XML alle Antworten bzw. alle Daten enthält. Nach einigen Fehlschlägen läuft es nun endlich unter Localhost. Für die Ausgabe:

Code: Alles auswählen

<?php

$client = new SoapClient&#40;"http&#58;//localhost/soap/meine.wsdl"&#41;;

  $params = "Du da mit dem Namen ...";
  $response = $client->ETWAS&#40;$params&#41;;

echo $response;

?>
Die "meine.wsdl" sieht zwar aus wie eine einfache XML, enthält aber keine Antworten oder verwertbare Daten, sondern teilt nur dem WSDL Server die gewünschte Funktion "ETWAS" mit:

Code: Alles auswählen

<soap&#58;binding style="rpc" transport="http&#58;//schemas.xmlsoap.org/soap/http" />
	  <operation name="ETWAS">
...
<soap&#58;address location="http&#58;//localhost/soap/mein-server.php" />
Und der Server führt die Funktion "ETWAS" aus:

Code: Alles auswählen

<?php
$server = new SoapServer&#40;"meine.wsdl"&#41;;

function ETWAS&#40;$ein_name&#41;&#123;

	return "Hallo, ".$ein_name;
&#125;

$server->AddFunction&#40;"ETWAS"&#41;;
$server->handle&#40;&#41;;
?>
Hatte mir zuvor einige Beispiele aus dem Web kopiert und unter Localhost abgespeichert, nur so zum Test wollte ich die xml.wsdl auslesen, erstaunt festgestellt, dass die ausgegebenen Namen nicht in der xml.wsdl vorkamen, weil da wohl die in der xml.wsdl enthaltene Adresse die Antworten lieferte.

Verfasst: 14.11.2012, 13:35
von nerd
Hm mir erschliesst sich der sinn immer noch nicht ganz. Das selbe kann ich doch auch via ajax erreichen. Ob der request dabei aus einem browser oder von einem anderen server kommt, und ich JSON oder XML verwende hat ja auch keinen einfluss darauf wie welche funktion ausgefuehrt wird - oder was uebersehe ich hier bzw. welches problem loest wsdl?

Verfasst: 14.11.2012, 13:57
von Melegrian
@nerd

Verstehe ich auch nicht und Ajax hat sich wohl nicht umsonst durchgesetzt.

@ Business-Experte

Unter /temp sollten eigentlich die letzten Antworten liegen, irgendwie finde ich die nicht, trotz der entsprechenden Einstellungen in der php.ini. Die letzte Antwort lässt sich jedoch auch so abspeichern:

Code: Alles auswählen

<?php

$option = array&#40;"trace" => 1&#41;;
				
$client = new SoapClient&#40;"http&#58;//localhost/soap/meine.wsdl", $option&#41;;

  $params = "Du da mit dem Namen ...";
  $response = $client->ETWAS&#40;$params&#41;;

echo $response."<br>";

$speichern = $client->__getLastResponse&#40;&#41;;  // letzte Antwort

file_put_contents&#40;"temp/test.xml", $speichern&#41;;

?>
Und enthält dann:

Code: Alles auswählen

<SOAP-ENV&#58;Envelope>...
<SOAP-ENV&#58;Body>...
Ich denke, es wird wärmer, was die Sessions-ID anbelangt:
Es funktioniert nur, wenn der Server die Funktionen von einer gesetzten Klasse exportiert
https://php.net/manual/de/soapserver.setpersistence.php

Da solltest Du Dir mal die erste Antwort abspeichern und zusätzlich mit

Code: Alles auswählen

var_dump&#40;$client->__getFunctions&#40;&#41;&#41;;
var_dump&#40;$client->__getTypes&#40;&#41;&#41;;
und was es da noch an Funktionen gibt, alles ansehen, was es zu sehen gibt.

Verfasst: 14.11.2012, 16:42
von Melegrian
Nun noch einmal, den Server umgestellt:

Code: Alles auswählen

<?php

class TEEC &#123; 

    function ETWAS&#40;$ein_name&#41;&#123;

	return "Hallo, ".$ein_name." Hokuspokus";
   &#125;
&#125;

$server = new SoapServer&#40;"meine.wsdl"&#41;;

$server->setClass&#40;"TEEC"&#41;;
$server->setPersistence&#40;SOAP_PERSISTENCE_SESSION&#41;;

$server->handle&#40;&#41;;

?>
Und da zeigt der Client den Cookie mit der PHPSESSID vom HTTP-Header an:

Code: Alles auswählen

<?php

$option = array&#40;"trace" => 1&#41;;
				
$client = new SoapClient&#40;"http&#58;//localhost/soap/meine.wsdl", $option&#41;;

  $params = "Du da mit dem Namen ...";
  $response = $client->ETWAS&#40;$params&#41;;

echo $response."<br>\n";
echo "<pre>".$client->__getLastResponseHeaders&#40;&#41;."</pre>\n";

$speichern = $client->__getLastResponse&#40;&#41;;  // letzte Antwort

file_put_contents&#40;"temp/test.xml", $speichern&#41;;



/* Ausgabe&#58;

Hallo, Du da mit dem Namen ... Hokuspokus

HTTP/1.1 200 OK
Date&#58; Wed, 14 Nov 2012 15&#58;32&#58;24 GMT
Server&#58; Apache/2.2.21 ......
X-Powered-By&#58; PHP/5.3.8
Set-Cookie&#58; PHPSESSID=7onrmp7bhv1h43khr4drintec7; path=/
.......
*/
?>
Somit brauchtest Du eigentlich nur kontrollieren, ob ein Sessions-Cookie vorhanden ist. Müsstest allenfalls dafür sorgen, dass ein Cookie gesetzt werden kann.

Verfasst: 14.11.2012, 18:36
von Business-Experte
Ich kann nicht so einfach den Server umstellen. Den eigenen nicht, da bin ich nur einer von vielen. Den Server mit dem Webservice natürlich auch nicht.

Ich muss die SessionId wohl irgendwie mittels der __setSoapHeaders-Funktion des in PHP eingebauten SOAP-Clients übermitteln.

Produziere da aber momentan noch 500 internal server error.

Verfasst: 14.11.2012, 18:40
von Business-Experte
nerd hat geschrieben:...
Die session_id wirst du wahrscheinlich an die request_ul anhaengen muessen; ...
Ja, neee....
Dafür muss man wohl eher das SOAPClient-Objekt nutzen. Ist in neueren Versionen von PHP "eingebaut" (Ab PHP5).

Verfasst: 15.11.2012, 16:39
von Melegrian
Bei meinen Tests gab es auch noch Probleme. Unter Localhost lief es, beim Test im Web erhielt ich ein 403 Forbidden. Unter Localhost wird bei jedem erneuten Aufruf eine neue ID ausgeliefert und die Abfrage mit

Code: Alles auswählen

if &#40;isset&#40;$_COOKIE&#91;"PHPSESSID"&#93;&#41;&#41; &#123; 
     
	echo "<br>Ja, die Session-ID ist ".$_COOKIE&#91;"PHPSESSID"&#93;."\n";

&#125; else &#123;echo "Nein\n";&#125;
liefert nur "Nein". Somit müsste die wohl irgendwie aus dem Response-Header ausgelesen werden, um dann mit session_id() an den Clienten durchzureichen, habe jedoch noch keine vernünftige Lösung gefunden. So sollte es eventuell gehen, wenn Du es schaffst die ID auszulesen und an session_id() zu übergeben.

Code: Alles auswählen

<?php
session_id&#40;"123abc124"&#41;;
session_start&#40;&#41;;

/*
Der restliche Code ...

*/ 


if &#40;isset&#40;$_COOKIE&#91;"PHPSESSID"&#93;&#41;&#41; &#123; 
     
	echo "<br>Ja, die Session-ID ist ".$_COOKIE&#91;"PHPSESSID"&#93;."\n";

&#125; else &#123;echo "Nein\n";&#125;

?>
Aus einem Kommentar:

Code: Alles auswählen

Leider musst du selber dafür sorgen, dass alle persistenten Werte in $_SESSION&#91;&#93; abgelegt werden, deine Objekte sind nicht automatisch persistent verfügbar.
https://heig.de/2009/03/php-webservice- ... ent-102906

Nun ließe sich zwar mit RegEx die Session-ID auslesen und an den Clienten weitergeben,

Code: Alles auswählen

$resh = $client->__getLastResponseHeaders&#40;&#41;;

if &#40;!empty&#40;$resh&#41;&#41; &#123;

	preg_match&#40;"#PHPSESSID=&#40;&#91;a-zA-Z0-9,-&#93;+&#41;#", $resh, $Sessifund&#41;;

	session_id&#40;$Sessifund&#91;1&#93;&#41;;
	session_start&#40;&#41;;
&#125;
dennoch halte ich das noch für keine richtige Lösung, da die server.php immer noch nichts davon weiß und weiterhin bei jedem Aufruf eine neue Session-ID sendet. Alles was ich bisher an Beispielen gefunden habe, scheint mehr oder weniger nicht zu funktionieren.

Da frage ich mich, um was für einen Webservice handelt es sich, haben die keine Dokumentation, aus der man etwas entnehmen könnte?

Verfasst: 17.11.2012, 09:39
von Melegrian
Mein letzter Ansatz den Response-Header auszulesen und die Session zu übernehmen, scheint vom Prinzip richtig gewesen zu sein, nur das die Übernahme nicht mit

Code: Alles auswählen

session_id&#40;$Sessifund&#91;1&#93;&#41;;

sondern mit

Code: Alles auswählen

$client->__setCookie&#40;Session-Id, $Sessifund&#91;1&#93;&#41;;

erfolgen sollte:

https://stackoverflow.com/questions/295 ... using-soap
https://php.net/manual/de/soapclient.setcookie.php

Kann es nur nicht testen, da unter Localhost die server.php blind bleibt und nichts mit $_COOKIE["..."] ausliest, wie weiter unten bei php.net erwähnt.

Auf den Servern (Webspaces) läuft es mit absoluten Pfadangaben nach eigenen Fehlerberichten und den Erfahrungen von anderen nur, wenn allow_url_fopen auf ON gesetzt ist und die Firewalls der Server keine Probleme bereiten.

An ON kann es bei mir nicht liegen, da stimmt alles, dennoch muss ich in der client.php und server.php relative Pfadangaben und in der datei.wsdl absolute Pfadangaben verwenden, wobei die client.php und datei.wsdl dadurch bedingt unter einer Domain erreichbar sein müssen, die server.php kann sich hingegen auf einem entfernten Server befinden. Habe es bisher jedoch nur auf zwei Servern getestet, da funktionierte es so.

Die SEOP-Bibliothek im Xampp scheint von 2005 zu sein und verwendet noch die eine oder andere ältere Funktion, die seit PHP 5.3 eigentlich nicht mehr verwendet werden sollte. Zumindest war eine Funktion mit einem Hinweis auf Deprecated bei bei php.net versehen, als ich nachschaute. Womit ich jetzt jedoch keine spezielle SEOP-Funktion meine, da die ja PHP 5 >= 5.0.1 sind.

Edit: Da in $client ein Objekt mit mehrdimensionalen Arrays enthalten ist, lässt sich auf preg_match und RegEx verzichten:

Code: Alles auswählen

// Die ersten Zeilen sind erst einmal richtig&#58;
$resh = $client->__getLastResponseHeaders&#40;&#41;;

if &#40;!empty&#40;$resh&#41;&#41; &#123;

	$Sessifund = $client->_cookies&#91;"PHPSESSID"&#93;&#91;0&#93;;
	
// Doch ab hier, so steht es geschrieben, ohne eine nachvollziehbare Wirkung&#58;	
	$client->__setCookie&#40;"PHPSESSID", $Sessifund&#41;;
	
/*
Doch nur so wird bei mir die PHPSESSID übernommen, wobei aber 
der Bezeichner der in der Session gespeicherten Klasse verloren geht&#58;
*/
	session_id&#40;$Sessifund&#41;;
	session_start&#40;&#41;;
&#125;
Ohnehin verstehe ich nicht so richtig, wie von einer entfernten Domain auf eine Session einer anderen Domain zugegriffen werden soll, das dürfte eigentlich nicht möglich sein. Irgendwo ist da noch ein Denkfehler vorhanden. Habe erst einmal ein überaltertes Buch bestellt, hoffe es bringt ein klein wenig. Um da etwas mehr durchzublicken, wird es wohl nicht anders abgehen, als sich Schritt für Schritt richtig einzuarbeiten.

Verfasst: 20.11.2012, 17:20
von Business-Experte
Anstatt Error 500 produziert mein Code inzwischen immerhin einen timeout. Aber soweit ich das überblicke, muss man die SessionId im Header setzen.

Verfasst: 20.11.2012, 18:33
von Melegrian
Hier mal die Bibliothek mit allen Klassen und in den Files der Bibliothek verwendeten Methoden:

https://pear.php.net/package/SOAP/docs/ ... _SOAP.html

Nicht dass ich richtig durchblicken würde, doch nun will ich es wissen. In einzelnen PHP Versionen soll es Bugs gegeben haben, zumindest steht das hier so.

https://grokbase.com/t/php/php-bugs/106 ... m-external

Komme mir vor wie ein Anfänger. An meinem ersten Script hatte ich auch vier Wochen gesessen und mehr als die Hälfte der Zeit nur nach Lösungswegen gesucht. Da das bei SOAP aber alles mehr oder weniger OOP ist, liegt es wohl an der fehlenden Einarbeitung. Das Problem ist ja, dass mich das Thema nicht mehr los lässt.

Bei eine normale Verbindung, da legt der Server unter /temp einen Sessions-Cookie ab und kappt die Verbindung. Der Browser speichert die Session im Verlauf, im Cache, im User Profil oder wo auch immer (habe es bisher nicht richtig herausgefunden, die wird zumindest nicht mit bei den normalen Cookies gespeichert, das habe ich überprüft) und bei jeder erneuten Anfrage wird die Sessid-Id wieder mit an den Server gesendet und verglichen, ob noch aktuell.

Wie aber nun, wenn sich zwei Server unterhalten? Auch da legt der Server die unter /temp ab und beide Server kappen die Verbindung bis zur nächsten Anfrage. Wie erinnert sich nun Server A an die Session mit Server B, um zu überprüfen, ob die Session-Id noch aktuell ist? Geht doch eigentlich (nach meinen gegenwärtigen Vorstellungen) nur über den Browser des Clienten, der zuerst bei Server A anfragt und Server A dann bei Server B.

Verfasst: 20.11.2012, 19:32
von Melegrian
Ich verstehe es gerade nicht, nur dass es die PHP Version ist, die ich im Xampp zu liegen habe:

PHP Version 5.3.8
https://bugs.php.net/bug.php?id=60481

Was soll das bedeuten, dass kein Cookie mit __setCookie gesendet werden kann, weil die WSDL geholt wird, noch bevor die Methode __setCookie aufgerufen wird?

Edit: Das Beispiel weiter unten auf der Seite mit "Output - first time rune" und "Output - second time" trifft es eigentlich recht gut:
SOAP_PERSISTENCE_SESSION no longer works
https://bugs.php.net/bug.php?id=34746