marcoborn
Goto Top

SOAP-Authentifizierung

Hallo Forum,
ich bin absoluter Neuling im Bereich SOAP und muss einen SOAP-Request aus Excel heraus starten.

Bei der Authentifizierung wird vom Webservice zusätzlich zu Nutzername und Passwort noch eine Mailadresse verlangt. Wie kann ich diese als 3. Parameter beim Open-Befehl mit übergeben? Oder gibt es einen anderen Weg, die Mailadresse mit zu übergeben?

Vielen Dank,
M. Born

Content-ID: 279246

Url: https://administrator.de/contentid/279246

Ausgedruckt am: 21.11.2024 um 21:11 Uhr

colinardo
colinardo 05.08.2015 aktualisiert um 10:35:11 Uhr
Goto Top
Hallo Marco,
das kommt darauf an wie der Webservice aufgebaut ist und in welchem XML Tag der Service die Mail-Adresse erwwartet. Normalerweise sendet man eine XML-Datei mit den Daten an den Webservice nachdem man die Verbindung aufgebaut hat, dazu solltest du die Doku zum Webservice konsultieren.
Ein Beipspiel wie man so was mit dem XMLHTTP Objekt macht, findest du hier
http://www.office-loesung.de/ftopic640714_0_0_asc.php (ganz unten)

Grüße Uwe
MarcoBorn
MarcoBorn 05.08.2015 um 12:46:05 Uhr
Goto Top
Hallo Uwe,
dieses Skript hatte ich auch als Basis für mein Makro genommen. Hier mein (anonymisierter) Code:
Private Sub CommandButton1_Click()
  Dim xmlhttp
  Dim user As String
  Dim pass As String
  Dim service As Integer

  user = "user"  
  pass = "password"  
  mail = "mail@test.de"  
  sURL = "https://myserver.de/soap/action"  
  service = 0

  
 Set xmlhttp = CreateObject("Msxml2.XMLHTTP")  
  Dim request
 
  'request = "<?xml version='1.0' encoding='utf-8'?>" & ...  
  request = "  <soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:urn=""urn:myserver.de"">" & _  
            "    <soapenv:Header/>" & _  
            "    <soapenv:Body>" & _  
            "      <urn:addCustomer>" & _  
            "       <clientHeader>" & _  
            "           <clientName>" & user & "</clientName>" & _  
            "           <clientEmail>" & mail & "</clientEmail>" & _  
            "           <clientPassword>" & pass & "</clientPassword>" & _  
            "       </clientHeader>" & _  
            "        <subscriberId>Test-SOAP-001</subscriberId>" & _  
            "        <country>DEU</country>" & _  
            "        <city>Berlin</city>" & _  
            "        <postalCode>10178</postalCode>" & _  
            "        <street>Alexanderplatz</street>" & _  
            "        <district/>" & _  
            "        <houseNumber>3</houseNumber>" & _  
            "      </urn:addCustomer>" & _  
            "    </soapenv:Body>" & _  
            "  </soapenv:Envelope>"  
  xmlhttp.Open "POST", sURL, False  
  xmlhttp.setRequestHeader "Content-Type", "text/xml"  
  xmlhttp.send (request)

  MsgBox (xmlhttp.responseText)
End Sub
Mit dem xmlhttp.Open kann ich Nutzername und Passwort als Parameter mit übergeben. Weitere Parameter sind jedoch nicht erlaubt. Scheinbar kann man die Parameter aber auch im Header mit übergeben, was ich mit meinem Code probiert habe. In der WSDL werden die 3 Parameter im Header auch so übergeben. Der ResponseText liefert mir die korrekten Datenfelder des SOAP-Services zurück, d.h. die Kommunikation mit dem Server scheint zu funktionieren. Allerdings erhalte ich immer die Meldung, dass Nutzername und Passwort nicht korrekt wären. Ich habe auch schon probiert, Nutzername und Mailadresse zu tauschen, aber es hat auch nicht funktioniert. Hast Du eine Idee, was ich falsch mache?

Vielen Dank,
Marco
colinardo
colinardo 05.08.2015 aktualisiert um 12:57:12 Uhr
Goto Top
Hast Du eine Idee, was ich falsch mache?
Ohne die Webservice-Definition und Anforderung zu kennen, leider schwer zu sagen face-sad
MarcoBorn
MarcoBorn 05.08.2015 um 13:32:25 Uhr
Goto Top
Hallo Uwe,
hier mal ein Auszu aus der WSDL. Der Rest sind weitere Funktionen wie ChangeCustomer, Delete Customer etc., die ich später auch noch hinzufügen werde. Für den Anfang muss ich aber erstmal eine Funktion zu Laufen kriegen.

<definitions name="soap" targetNamespace="urn:myserver.de">  
  <types>
    <schema targetNamespace="urn:myserver.de">  
      <xsd:element name="addCustomerRequest" type="tns:addCustomerRequest"/>  
      <xsd:element name="addCustomerResponse" type="tns:addCustomerResponse"/>  
      <xsd:complexType name="addCustomerRequest">  
        <xsd:sequence>
          <xsd:element name="clientHeader" type="tns:clientHeader"/>  
          <xsd:element name="subscriberId" type="xsd:string"/>  
          <xsd:element name="country" type="xsd:string"/>  
          <xsd:element name="city" type="xsd:string"/>  
          <xsd:element name="postalCode" type="xsd:string"/>  
          <xsd:element name="street" type="xsd:string"/>  
          <xsd:element name="district" type="xsd:string"/>  
          <xsd:element name="houseNumber" type="xsd:string"/>  
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="addCustomerResponse">  
        <xsd:sequence>
          <xsd:element name="subscriberId" type="xsd:string"/>  
          <xsd:element name="resultCode" type="xsd:int"/>  
          <xsd:element name="resultMessage" type="xsd:string"/>  
          <xsd:element name="resultAdditionalInformation" type="xsd:string"/>  
      </xsd:complexType>
      <xsd:complexType name="clientHeader">  
        <xsd:sequence>
          <xsd:element name="clientName" type="xsd:string"/>  
          <xsd:element name="clientEmail" type="xsd:string"/>  
          <xsd:element name="clientPassword" type="xsd:string"/>  
        </xsd:sequence>
      </xsd:complexType>
    </schema>
  </types>
  <message name="soap_addCustomer">  
    <part element="tns:addCustomerRequest" name="addCustomerRequest"/>  
  </message>
  <message name="soap_addCustomerResponse">  
    <part element="tns:addCustomerResponse" name="addCustomerResponse"/>  
  </message>
   <portType name="soap_port">  
    <operation name="addCustomer" parameterOrder="addCustomerRequest">  
      <input message="tns:soap_addCustomer"/>  
      <output message="tns:soap_addCustomerResponse"/>  
    </operation>
  </portType>
  <binding name="soap_binding" type="tns:soap_port">  
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>  
    <operation name="addCustomer">  
      <soap:operation soapAction="urn:myserver.de/addCustomer"/>  
        <input>
          <soap:body use="literal"/>  
        </input>
        <output>
          <soap:body use="literal"/>  
        </output>
     </operation>
     </binding>
    <service name="service">  
      <port name="soap_port" binding="tns:soap_binding">  
        <soap:address location="http://myserver.de/soap/action"/>  
      </port>
    </service>
  </definitions>
Ich hoffe, Du kannst mir mit diesen Infos etwas weiterhelfen.

Viele Grüße,
M. Born
122990
122990 05.08.2015 aktualisiert um 15:04:26 Uhr
Goto Top
Moin zusammen,
du schließt ja mit <soapenv:Header/> in deinem Code ja den Header schon ab also landen deine Headereinträge nicht im Header der Nachricht ...
https://www.teialehrbuch.de/Kostenlose-Kurse/XML/7883-Der-syntaktische-A ...

btw. ist das leider kein valides *.wsdl Dokument, wahrscheinlich mal wieder aus dem IE rauskopiert face-sad

Gruß grexit
MarcoBorn
MarcoBorn 05.08.2015 um 16:49:17 Uhr
Goto Top
Hallo Grexit,
ich habe meinen Code mit Hilfe eines SOAP-Test-Tools laufen laufen und dort ist das Ganze problemlos gelaufen. Daher habe ich das hier auch so probiert. Wie müßte ich denn meinen Code umbauen, dass e läuft? Nur den Client-Header-Teil in den Header packen, oder den ganzen Block mit addCustomer? Dann wäre ja im Body nichts mehr drin. Gäbe das dann nicht auch Probleme?

Viele Grüße,
Marco
122990
122990 05.08.2015 aktualisiert um 17:06:19 Uhr
Goto Top
Zitat von @MarcoBorn:
ich habe meinen Code mit Hilfe eines SOAP-Test-Tools laufen laufen und dort ist das Ganze problemlos gelaufen.
Naja da fehlen die ganzen Standard Namspaces die das File als *.wsdl identifizieren und außerdem ist dort ein Tag nicht geschlossen (<xsd:sequence> in Zeile 19), und die XML Declaration fehlt, also mitnichten valide! Du hast den Code wahrscheinlich aus dem IE kopiert ... das gibt immer nur Schrott, also poste mal den funktionsfähigen WSDL-Code.

hier auch so probiert. Wie müßte ich denn meinen Code umbauen, dass e läuft? Nur den Client-Header-Teil in den
Header packen, oder den ganzen Block mit addCustomer? Dann wäre ja im Body nichts mehr drin. Gäbe das dann nicht auch Probleme?
Lass dir einen validen Envelope doch einfach generieren, dafür gibts Online-Tools ...
MarcoBorn
MarcoBorn 05.08.2015 um 17:13:14 Uhr
Goto Top
Wie gesagt, habe ich den Code aus der WDSL herauskopiert und die anderen Methoden gelöscht. Kann sein, dass ich eine Zeile zu viel gelöscht habe. Ich habe es mit dem Firefox kopiert; den IE nutze ich nicht.

Die WSDL ist schon im Einsatz mit einem anderen Client (der leider von einer anderen Firma entwickelt wurde) und ich soll jetzt dazu einen Client auf Excel-Basis bauen. Wie gesagt, die WSDL funktioniert und ich brauche nur einen Weg, das Ganze in VBA-Code umzusetzen.
122990
122990 05.08.2015 aktualisiert um 17:23:43 Uhr
Goto Top
Wie geschrieben lad das WSDL-File in den Generator und dir wird ein valider Envelope ausgeworfen den du nutzen kannst, dann sollte das laufen.
colinardo
colinardo 05.08.2015, aktualisiert am 06.08.2015 um 11:00:14 Uhr
Goto Top
@122990 hat recht, das WSDL File sollest du auch in Firefox nur über Kontextmenü > Seitenquelltext kopieren dann ist es auch valide! Nur das was Firefox direkt anzeigt ist gerenderter Mist, da fehlt die Hälfte.

Dein Code ist schon fast korrekt, nur die XML Declaration fehlt
request = "<?xml version=""1.0"" encoding=""utf-8""?>" & _ 
Dann würde ich den Content-Type noch explizit angeben wenn im Passwort Sonderzeichen vorkommen:
xmlhttp.setRequestHeader "Content-Type", "text/xml; charset=utf-8"  
Dann ist es in manchen Fällen noch nötig den Header SOAPAction zu definieren und ihr die Funktions-URL als Parameter mitzugeben:
xmlhttp.SetRequestHeader "SOAPAction", "http://myserver.de/soap/action/addCustomer"  
(Bitte auf Groß- und Kleinschreibung der Methoden achten)

Das hat hier mit einem Service den ich hier mal testweise eingerichtet habe, einwandfrei funktioniert.

Wenn du Zweifel hast, zeichne einfach einen funktionierenden Request mit Wireshark oder mit den Browser-DeveloperTools (F12 > Tab Netzwerkanalyse) auf, dort siehst du was für einen XML-Envelope der Client an den Service schickt und kannst dein Envelope entsprechend anpassen.

Ohne weitere Info zum Dienst ist hier ein Debugging über die Ferne für mich schwierig, das wirst du verstehen.

Wenn man wüsste von welchem Hersteller/Dienst der Service bereitgestellt wird, könnte man die Doku konsultieren.

Noch zur Info: Die Parameter bei der Funktion "Open" für Username und Passwort gelten nur wenn die Website mit Standardauthentifizierung abgesichert ist, d.h. wenn man die Seite im Browser aufruft und eine Authentifizierungsabfrage erscheint.

Grüße Uwe
MarcoBorn
MarcoBorn 06.08.2015 um 14:08:14 Uhr
Goto Top
Hallo Uwe und grexit,
ich habe jetzt die Anmerkungen von Uwe eingearbeitet und auch mit Hilfe von http://soapclient.com/soapclient mir aus der WSDL eine SOAP-Message generieren lassen. Diese habe ich jetzt in mein VBA-Makro reinkopiert. Jetzt erhalte ich stattdessen die Meldung:
<?xml version="1.0" encoding="UTF-8"?>  
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  
  <soap:Body>
    <soap:Fault>
      <faultcode>Server</faultcode>
      <faultstring>Cannot find SOAP action mapping for http://myserverde/soap/action/addCustomer</faultstring>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

Die mir von SOAP Message Builder generierte Nachricht sieht wie folgt aus:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="urn:ecr.doksysteme.de" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" > 
  <SOAP-ENV:Body>
    <mns1:addSubscriberRequest xmlns:mns1="urn:ecr.doksysteme.de"> 
      <clientHeader>
        <clientName></clientName>
        <clientEmail></clientEmail>
        <clientPassword></clientPassword>
      </clientHeader>
    <subscriberId></subscriberId>
    <country></country>
    <city></city>
    <postalCode></postalCode>
    <street></street>
    <district></district>
    <houseNumber></houseNumber>
    </mns1:addSubscriberRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Scheinbar funktioniert jetzt die Authentifizierung, aber irgendwtwas anderes ist verkehrt. Ich habe in die Nachricht noch die Werte für Nutzername, PW, Straße, Ort etc. eingegeben, aber auch dann funktioniert es nicht. Mache ich noch was anderes falsch?
colinardo
colinardo 06.08.2015 aktualisiert um 14:15:02 Uhr
Goto Top
Cannot find SOAP action mapping for http://myserverde/soap/action/addCustomer
Dann lass den SOAPAction Header mal weg, die URL die du brauchst kenne ich leider nicht, die musst du schon anpassen (das war ja nur eine Beispiel-URL).
MarcoBorn
MarcoBorn 06.08.2015 um 14:42:18 Uhr
Goto Top
Wenn ich die Zeile
xmlhttp.setRequestHeader "SOAPAction", "http://testsever.de/soap/action/addCustomer"  
auskommentiere, erhalte ich dieselbe Fehlermeldung wie zuvor mit dem fehlenden SOAP binding.
122990
122990 06.08.2015 aktualisiert um 14:53:35 Uhr
Goto Top
Wie wärs mal wenn du den Hersteller des Dienstes nennst ? Oder die Doku konsultierst.
Du weißt schon das das hier Raten mit der Glaskugel bedeutet, ohne das URL Schema zu kennen.

Nehm doch einfach Wireshark wie @colinardo vorgeschlagen hat, damit ist das in 0 komma nix erledigt ... und du siehst was für Daten wie übertragen werden müssen!
MarcoBorn
MarcoBorn 06.08.2015 um 15:35:23 Uhr
Goto Top
Außer der WSDL habe ich weiter keine Doku. Ich weiss noch, welche Felder jeweils an den Server übertragen werden und wie ich die Antworten interpretieren muss. Wireshark hilft mir auch nicht weiter, weil das Ganze über TLS verschlüsselt ist.