Donnerstag, 4. Dezember 2008





April 2006
aus Ausgabe: 3.2002
Seifenkiste
Das Microsoft SOAP Toolkit
von Christian Gross

Web Services und SOAP sind neue Technologien, für die sich Unternehmen wie Microsoft in letzter Zeit ereifert haben. Abgesehen vom Hype hat SOAP bisher jedoch noch keinen großen Eindruck in der Geschäftswelt hinterlassen. Dies liegt nicht an Problemen der Web Services an sich, sondern daran, dass wir uns in einer Phase des Übergangs von der traditionellen Anwendungsentwicklung zur Entwicklung verteilter Anwendungen befinden. Wir sind gewohnt, alle Teile unserer Anwendung in der Hand zu haben.


Lassen Sie mich dies durch das Beispiel der Banken im Wilden Westen illustrieren. Anfänglich misstrauten die Menschen der Bank, da sie nicht glaubten, dass die Bank ihnen ihr Geld zurückgeben würde. And am Anfang hatten die Leute auch recht. Nachdem einige Zeit vergangen ist, behält jedoch kaum noch jemand all sein Geld unter dem Kopfkissen. Das Gleiche wird mit Web Services passieren. Warum diese lange Vorrede über web Services? Weil das Microsoft SOAP Toolkit 3.0 eines der ersten Toolkits ist, das sowohl für Legacy-Anwendungen geeignet ist als auch die neuen Web Services-Technologien integriert.

Das Microsoft SOAP Toolkit und Microsoft .NET Web Services sind nicht das selbe. Es handelt sich um zwei verschiedene Umgebungen und zwei separate Toolkits. Das Microsoft .NET Web Services Toolkit ist für die Verwendung innerhalb des .NET Frameworks bestimmt. Das Microsoft SOAP Toolkit soll in Legacy-Umgebungen eingesetzt werden, in denen die primäre Komponententechnologie COM und ASP oder ISAPI (Internet Server API) ist. Ich werde hier allerdings nicht die Performanz- oder technologischen Unterschiede zwischen SOAP Toolkit und .NET Web Services beschreiben.

Zum Zeitpunkt der Niederschrift lag das Microsoft SOAP Toolkit in Version 3.0 vor und war das erste seiner Art, das die Probleme der Verwendung von Web Services in komplexeren Umgebungen adressierte. So ist im Toolkit beispielsweise die Fähigkeit enthalten, One-Way Messages zu versenden.

Wo anfangen?
Wenn ich Microsoft-Technologien einsetze, ist es oft möglich, herumzuklicken, zu experimentieren und auf diese Weise herauszufinden, wie etwas funktioniert. Das SOAP Toolkit ist anders, da es hier sehr wenig zum Klicken gibt. Wenn Sie das Microsoft SOAP Toolkit installiert haben, sehen Sie zum Beispiel die in Abbildung 1 gezeigten neuen Menüeinträge. Diese Anwendungen lassen den Entwickler nicht unbedingt den Eindruck gewinnen, dass er tatsächlich so etwas wie ein SOAP Toolkit installiert hat. Es gibt nichts, das sagt: Generiere SOAP-Kram. Und wenn die Hilfe geöffnet wird, enthält die Dokumentation keinen Punkt: Baue Web Services-Kram. Stattdessen enthalten die Hilfe-Dateien Erklärungen von WSDL, WSML und ähnlichen Dingen. Dies stürzt den Entwickler in tiefe Verwirrung, weil er sich fragt, wo all das Point-and-Click des Microsoft .NET Web Services Toolkits geblieben ist.


Abb. 1: Menüeinträge nach der Installation


Der Grund hierfür liegt darin, dass das SOAP Toolkit für den Einsatz in mehrsprachigen, multiplen Umgebungen intendiert ist. Es ist beispielsweise möglich, das Microsoft SOAP Toolkit innerhalb des Apache Frameworks einzusetzen und Python als Programmiersprache zu verwenden. Microsoft kann nicht alle Programmiersprachen unterstützen. Was sie jedoch tun können, ist, ein möglichst einfaches und generisches Toolkit zur Verfügung zu stellen, das einen größtmöglichen Teil des SOAP-Standards implementiert. Diese Anforderungen erfüllt das SOAP Toolkit.

Der SOAP Server
Einen Web Service zu schreiben, ist nicht schwierig: Es kann ausreichen, ein COM-Objekt zu exponieren. Schauen Sie sich den VB-Quellcode in Listing 1 an. Es handelt sich um einen einfachen Taschenrechner, der addieren, subtrahieren, multiplizieren und dividieren kann. Die Methoden sind dabei einfach und wohl definiert. Die Input-Parameter für jede Methode sind Standard-Datentypen und nicht etwa komplexe Klassen oder Strukturen. Auch die Rückgabe-Datentypen sind Standard-Datentypen.



Listing 1

Option Explicit

Public Function Add(ByVal A As Double, ByVal B As Double) As Double
Add = A + B
End Function

Public Function Subtract(ByVal A As Double, ByVal B As Double) As Double
Subtract = A - B
End Function

Public Function Multiply(ByVal A As Double, ByVal B As Double) As Double
Multiply = A * B
End Function

Public Function Divide(ByVal A As Double, ByVal B As Double) As Double
Divide = A / B
End Function

Um diese Klasse als Web Service bereitzustellen, benutzt man die Anwendung WSDL Generator, auf die weiter unten noch eingegangen wird. Im ersten Schritt wird die VB-Komponente in eine DLL kompiliert, die eine COM-Komponente darstellt. Wenn die Kompilierung erfolgreich abgeschlossen wurde, kann der WSDL Generator gestartet werden. Als erstes erscheint der Dialog in Abbildung 2.


Abb. 2: Begrüßungsdialog des WSDL Generator


Abb. 3: Auswahl des COM-Objekts


Durch Klicken auf Next erscheint der nächste Dialog, der das optionale Spezifizieren einer Konfiguration ermöglicht. Da wir keine Default-Settings verwenden, klicken wir auf Next und erhalten den Dialog in Abbildung 3. Im Textfeld geben wir Calculator als Namen für den Service ein; der lokale Pfad sollte zu dem COM-Objekt, das aus der VB-Quelle kompiliert wurde, führen. Mit diesem Dialogschritt wird das COM-Objekt definiert, das als Web Service exponiert werden soll.

Wenn Sie Next drücken, erscheint der Dialog in Abbildung 4. In diesem Schritt hat die Anwendung WSDL Generator das im vorausgegangenen Schritt referenzierte COM-Objekt geladen. Nach dem Laden werden die exponierten Interfaces und Methoden angezeigt. Es ist möglich, bestimmte COM-Interfaces und Methoden auszuwählen. Für unsere Demonstration soll jedoch einfach das Listenelement Calculator gewählt werden, um alle Methoden und Interfaces zu selektieren.


Abb. 4: Auswahl der Methoden


Abb. 5: Auswahl des Listener Type


Wenn Sie auf Next geklickt haben, erscheint der Dialog in Abbildung 5. Die URI-Textbox definiert den Ort, an dem sich die WSDL-Datei befindet. Der Listener Type bestimmt, wie der Web Service-Request vom Webserver verarbeitet wird. Für unsere Demo wählen wir ISAPI aus. Wenn der Listener-Typ ASP gewählt würde, würde die URI eine ASP-Seite spezifizieren, die die SOAP-Anfragen behandelt. In beiden Fällen bilden die WSDL- und die WSML-Datei die Internet Type Library des Web Services. Der Unterschied zwischen den Listener-Typen besteht darin, dass der ISAPI-Listener frühes und der ASP-Listener spätes Binding verwendet.

Wenn zum Beispiel ein SOAP-Request an den ISAPI-Listener gerichtet wird, dann wird dieser die Anfrage direkt parsen und an die zuvor erstellte COM-Komponente senden. Wenn jedoch ein ASP-Listener spezifiziert wurde, bindet das ASP-Skript die WSDL- und WSML-Dateien zusammen und schickt die Anfrage an die COM-Komponente. Der Vorteil des ISAPI-Ansatzes liegt darin, dass dieser schneller ist und sich gut für SOAP-Requests eignet, die unverändert bleiben oder nicht vom Aufrufer abhängig sind. Der Vorteil des ASP-Ansatzes besteht hingegen darin, dass die SOAP-Behandlung dynamisch verändert werden kann, dafür aber langsamer ist.


Abb. 6: URIs der WSDL-Datei


Im nächsten Dialog (siehe Abb. 6) bezeichnen die generierten URIs die verschiedenen URIs der WSDL-Datei. Per Default wird die Domain tempuri.org verwendet, der in den Namen der eigenen Domäne geändert werden sollte. Beachten Sie dabei, dass die definierten URIs nicht tatsächliche Server-URIs sind, sondern als eindeutige Tokens zur Identifizierung spezifischer Teile der WSDL-Datei dienen. Ändern Sie den Domänen-Namen und rufen Sie mit Next den letzten Dialog auf. Hier wird bestimmt, wo die WSDL- und WSML-Dateien gespeichert werden sollen. Übernehmen Sie die Default-Werte, klicken auf Next und beenden Sie mit Finish.

Was haben wir getan?
Mit den gezeigten Schritten wurden eine WSDL- und eine WSML-Datei generiert. Beide Dateien dienen als Kitt. Die WSDL-Datei beschreibt das Was des Web Services. Die WSML-Datei spezifiziert das Binding zwischen der WSDL-Datei und der COM-Komponente. Eine direkte Bindung der COM-Komponente innerhalb der WSDL-Datei selbst ist nicht möglich. Nebenbei bemerkt, tun viele andere Frameworks das Gleiche, zum Beispiel Apache Axis mit der Verwendung der WSDD-Datei.

Bei der Verwendung des ISAPI-Listeners geschieht die WSDL-Übersetzung in einen COM-Komponenten-Aufruf wie gesagt automatisch. Der ASP-Listener funktioniert ähnlich, nur dass Sie hier jede Methode einzeln aufrufen müssen. Um ISAPI besser zu verstehen, wäre es daher interessant, sich etwas ASP-Code anzusehen.



Listing 2

<%@ LANGUAGE=VBScript %>
<%
Option Explicit
On Error Resume Next
Response.ContentType = "text/xml"
Dim SoapServer
If Not Application("CalcAspVbsVbInitialized") Then
Application.Lock
If Not Application("CalcAspVbsVbInitialized") Then
Dim WSDLFilePath
Dim WSMLFilePath
WSDLFilePath = Server.MapPath("Calc.wsdl")
WSMLFilePath = Server.MapPath("Calc.wsml")
Set SoapServer = Server.CreateObject("MSSOAP.SoapServer30")
If Err Then SendFault "Cannot create SoapServer object. " & Err.Description
SoapServer.Init WSDLFilePath, WSMLFilePath
If Err Then SendFault "SoapServer.Init failed. " & Err.Description
Set Application("CalcAspVbsVbServer") = SoapServer
Application("CalcAspVbsVbInitialized") = True
End If
Application.UnLock
End If
Set SoapServer = Application("CalcAspVbsVbServer")
SoapServer.SoapInvoke Request, Response, ""
If Err Then SendFault "SoapServer.SoapInvoke failed. " & Err.Description
Sub SendFault(ByVal LogMessage)
Dim Serializer
On Error Resume Next
' "URI Query" logging must be enabled for AppendToLog to work
Response.AppendToLog " SOAP ERROR: " & LogMessage
Set Serializer = Server.CreateObject("MSSOAP.SoapSerializer30")
If Err Then
Response.AppendToLog "Could not create SoapSerializer30 object. " & Err.Description
Response.Status = "500 Internal Server Error"
Else
Serializer.Init Response
If Err Then
Response.AppendToLog "SoapSerializer.Init failed. " & Err.Description
Response.Status = "500 Internal Server Error"
Else
Response.Status = "500 Internal Server Error"
Serializer.startEnvelope
Serializer.startBody
Serializer.startFault "Server", "The request could not be processed due to a problem in the server. Please contact the system admistrator. " & LogMessage
Serializer.endFault
Serializer.endBody
Serializer.endEnvelope
If Err Then
Response.AppendToLog "SoapSerializer failed. " & Err.Description
Response.Status = "500 Internal Server Error"
End If
End If
End If
Response.End
End Sub
%>

Betrachten Sie den ASP SOAP Toolkit-Glue Code in Listing 2. Der erste Schritt besteht darin herauszufinden, ob der CalcAspVbsVbServer initialisiert ist. Die Applikation CalcAspVbsVbServer enthält Referenzen auf die WSDL- und WSML-Dateien und die COM-Komponente SoapServer30. SoapServer30 ist die Black Box, die die WSML- und die WSDL-Datei nimmt, die beiden verbindet und einen Stub generiert, der die COM-Komponente aufruft. Man macht aus diesem Objekt ein Objekt auf Anwendungsebene, um die WSDL- und WSML-Informationen beim ersten Aufruf des Web Service zu kompilieren. Nach der Kompilierung geht die Erstellung der Verweise zwischen SOAP-Request und COM-Request sehr viel schneller vonstatten. Nach seiner Initialisierung wird die SOAP-Anfrage über die Methode SoapInvoke an die SoapServer30-COM-Komponente gesendet. Mit dem Aufruf von SoapInvoke werden die Request-Daten eingelesen, die COM-Komponente aufgerufen und die Anwort in einen XML-Stream kodiert, der dann an das ASP-Response-Objekt geschickt wird.

Um einen SOAP-Fault zu senden, wird die ASP-Funktion SendFault verwendet. Interessant ist an dieser Funktion, dass ein Lower-Level-Objekt namens Serializer aufgerufen wird. das Serializer-Objekt ist Teil des SOAP Toolkits und ermöglicht es dem Entwickler, die SOAP-Response manuell zu erstellen. In unserem Fall wird die SOAP-Anwort mit den folgenden Methoden erstellt:
  • Serializer.startEnvelope: erstellt den SOAP-Envelope.
  • Serializer.startBody: erstellt die definition des SOAP-Body.
  • Serializer.startFault: erstellt die SOAP-Fault-Definition, wobei Werte über die Parameter spezifiziert werden.
  • Serializer.endFault: schließt die SOAP-Fault-Definition.
  • Serializer.endBody: schließt die SOAP-Body-Definition.
  • Serializer.endEnvelope: schließt den SOAP-Envelope.

Nach diesen Methodenaufrufen erhalten wir folgenden XML-Code:

<envelope><body><fault></fault></body></envelope>

Es mag etwas albern erscheinen, Methodenaufrufe zu verwenden, um den XML-String zu erzeugen. Tatsächlich ist es aber eine gute Lösung, da die SOAP-Spezifikation viele kleine Details erfordert. SOAP erfordert beispielsweise Namespaces, die in unserem Beispiel allerdings nicht vorkommen. Der Serializer fügt diese kleinen Details automatisch hinzu.

Die Betrachtung des ASP-Codes hat verdeutlicht, dass es einen High-Level- und einen Low-Level-Ansatz zur Behandlung von Web Service-Requests gibt. Der High-Level-Ansatz besteht in der Verwendung SoapServer30-Komponente - und man benötigt im Grunde kein Wissen darüber, was ein Web Services ist, um den WSDL Generator zu verwenden. Der Low-Level-Approach andererseits setzt voraus, dass der Programmierer SOAP und seinen Aufbau versteht. Der Vorzug dieses Ansatzes liegt darin, dass ein individuelles Tuning von SOAP-Request bzw. -Response möglich ist.

Der SOAP-Client
Um mit dem Server kommunizieren zu können, müssen wir einen Client schreiben. Der Client kann den Server mit dem folgenden VB-Quellcode aufrufen:

result = mSoapClient.Add( 23, 45)

Die Einfachheit dieses Codes ist beeindruckend, dieser verbirgt jedoch einiges. Zunächst verbirgt er, wo die Add-Methode des Objekts mSoapClient definiert wird, und wie die Daten zu Web Service geschickt werden. Diese Informationen werden von der WSDL-Datei geliefert, die vom WSDL Generator generiert wurde. Wir haben die WSDL-Datei weiter oben als die Typbibliothek eines SOAP-Requests definiert. Und der Client, das Objekt mSoapClient, benutzt die WSDL-Datei, um zu entschlüsseln, welche Methoden zur Verfügung stehen und wie sie aufgerufen werden. Das mSoapClient-Objet wird mit folgendem Code initialisiert:

Set mSoapClient = New MSSOAPLib30.SoapClient30

mSoapClient.MSSoapInit2 _
App.Path & "/Calc.wsdl", _
"", _
"Calc", _
"CalcSoapPort", _
"http://tempuri.org/Calc/wsdl/"

Die COM-Komponente SoapClient30 verwaltet dabei die Internet-Tybbibliothek und die WSDL_Datei wird über die Methode MSSoapInit2 referenziert. Beachten Sie, dass die Referenz auf die WSDL-Datei auf eine lokale Datei (App.Path) verweist, nicht auf eine Datei im Internet. Dies liegt darin begründet, dass die WSDL-Spezifikation keinen Internet-Download fordert. Der andere Methodenaufruf, der notwendig ist, bevor der eigentliche VB-Clientaufruf ausgeführt werden kann, ist die Angabe des URL, an den der SOAP-Request geleitet werden soll. Dies geschieht mit folgendem Code:

mSoapClient.ConnectorProperty("EndPointURL") = "http://www.myserver.com/uri_ASP_Or_WSDL"

Jetzt ist alles bereit, damit der ursprüngliche Client-Methodenaufruf funktionieren kann. Bei dem gezeigten Ansatz handelt es sich um den High-Level-Ansatz. Wie beim Server-Beispiel ist es auch hier möglich, einen Low-Level API-Ansatz zu verfolgen. Nur würde der Entwickler in diesem Fall die COM-Komponenten SoapSerializer30 und SoapReader30 benutzen, um die SOAP-Requests von Hand zu erstellen.

Sicherheit implementieren
Die erzeugten SOAP-Requests und -Responses benutzen Klartext. Dies wäre natürlich ein unzureichender Ansatz, wenn es sich bei den übermittelten Daten um kritische handelte. Kritische Daten machen die Verwendung von Technologien wie SSL erforderlich. Dies ist mit der Microsoft-Infrastruktur sehr einfach zu bewerkstelligen und erfordert die Angabe eines anderen Endpunkt-URL:

mSoapClient.ConnectorProperty("EndPointURL") = "https://www.myserver.com/uri_ASP_Or_WSDL"

Der Unterschied besteht in der Verwendung von https, womit die Verwendung des SSL-Protokolls angezeigt wird. Es ist dabei erforderlich, dass auf dem Server ein SSL-Zertifikat installiert ist. Um ein solches zu installieren, folgen Sie einfach den IIS-Instruktionen.

Bevor ich fortfahre, möchte ich kurz SSL erläutern, da viele Entwickler, die SSL nicht verstehen, immer wieder versuchen, ihre eigenen Sicherheits- oder Verschlüsselungssystem zu implementieren. SSL ist sehr simpel, erfordert jedoch einige Standard-Schritte. SSL verwendet eine Kombination aus Public Key Encryption und Stream Encryption. Wenn man zum Beispiel bei Verisign ein Zertifikat anfordert, handelt es sich um einen Public/Private Key-Block, der die individuellen Encryption-Schlüssel enthält. Die Public/Private Key-Kombination fordert man bei einem Unternehmen wie Versign an, da dieses für einen bürgt. Diese Bürgschaft wird ausgeführt, wenn eine dritte Partei bestimmte Daten mit einem spezifischen Public Key verschlüsseln will. Der eingeschickte Schlüssel wird gegen den von Verisign verwalteten geprüft und dann entweder ein Okay oder ein Denial zurückgeschickt. Das Unternehmen Verisign agiert also als eine Art öffentliches Directory.

Nachdem der Public Key verifiziert wurde, verschlüsselt der Client eine vom Client generierte Passwort-Datei und sendet diese an den Server. Die Kombination aus Public und Private Key ermöglicht die Verschlüsselung von Daten unter Verwendung eines Passworts. Das Problem dabei ist, dass Sender und Empfänger das selbe Passwort verstehen müssen. Wie also gibt man das Passwort an den Empfänger weiter? Sicherlich nicht per Klartext über das Internet oder unter Verwendung eines Standard-Passworts. Das ursprüngliche Versenden eines Passworts ist immer das schwächste Glied im Verschlüsselungsprozess. Public Key Encryption löst dieses Problem, da mit einem öffentlich verfügbaren Public Key verschlüsselte Daten nur mit einer Kombination aus Public Key und generiertem Private Key entschlüsselt werden können. Der Private Key wird dabei auf dem Server aufbewahrt. Wenn der Client die verschlüsselten Daten an den Server schickt, verwendet dieser den Private Key, um das Passwort zu entschlüsseln, das benutzt wird, um den XML-Stream zu verschlüsseln.

SSL ist per Default in den meisten HTTP-Frameworks implementiert und ein plattformübergreifender Standard. das heißt, dass eine von Axis hergestellte SSL-Verbindung eine Kommunikation mit dem SOAP Toolkit ermöglicht.

Was Sie sonst noch wissen sollten
Wenn Sie die anfänglichen Hürden des SOAP Toolkits überwunden haben, werden Sie erkennen, dass dieses auf zwei Entwicklungszweige abgestimmt ist: High-Level und Low-Level API-Entwickler. Der High-Level API-Entwickler benötigt eine funktionierende WSDL-Datei, während der Low-Level API-Entwickler mit oder ohne WSDL-Datei arbeiten kann, da er über ein tiefes Wissen der SOAP_Spezifikation verfügt.

Eine weitere Frage, die sich stellt, ist, ob das Microsoft SOAP Toolkit nur mit Microsoft Internet Server funktioniert. Die Antwort ist, dass das SOAP Toolkit mit jedem Webserver, der COM unterstützt, zusammenarbeitet. Wenn Sie sich an den Black Box-Ansatz des Servers erinnern, so implementierten dort ASP-Request und -Response das COM-Serialisierungs-Interface, das den XML-Content streamt und persisitiert. Ein anderer Entwickler könnte das COM-Serialization-Interface implementieren und den XML-Stream mittels Internet-Prokollen oder Dateien manipulieren.

Fazit
Das Microsoft SOAP Toolkit ist eine Umgebung, die Windows-Entwickler gerichtet ist, die nicht die .NET-Plattform verwenden. Es handelt sich nicht um eine begrenzte oder vereinfachte Version des .NET Web Services Toolkits, sondern um einen eigenständigen, vollständigen Satz von Werkzeugen für das Schreiben von SOAP 1.2 Web Services. Ich persönlich, der ich sonst Apache und C++ verwende, halte es für eine ausgezeichnete Plattform, da ich mich nicht wie ein Bürger zweiter Klasse halten muss wie beim .NET Framework. Da ich schon eine Weile mit SOAP gearbeitet habe, gilt meine einzige Sorge - und das trifft auf alle SOAP Toolkits zu - der Interoperabilität. Dies ist und bleibt der eigentliche Knackpunkt.

Wenn Sie weitere Fragen zum Thema haben, erreichen Sie Christian Gross unter contact@devspace.com oder über seine Website www.devspace.com.

Links und Literatur


    Hat Ihnen dieser Artikel gefallen? Dann abonnieren Sie das Entwickler Magazin direkt über unser Online-Formular.

zur vorherigen Seite
zurück
an den Anfang der Seite
nach oben
Diesen Artikel drucken
drucken
Diesen Artikel weiterempfehlen
empfehlen




Software & Support Verlag GmbH