PHP SOAP Server mit WSDL und API Schlüssel

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • In diesem Tutorial wird die Einrichtung eine kennwortgeschützten SOAP Servers mit WSDL Unterstützung erklärt.
    In diesem Tutorial wird die Einrichtung eine kennwortgeschützten SOAP Servers mit WSDL Unterstützung erklärt.

    Damit wir den SOAP Server erweitern können, erstellen wir erstmal eine Kindklasse vom SOAP Server. Dieser bringen wir nichts weiteres bei als die WSDL Funktion.
    An der WSDL Funktion scheitern leider die meisten Implementierungen. Sie gibt die Spezifikationen vor, die es ermöglichen einen SOAP Server auch mit anderen Clients zu nutzen - wie z.B. Java.

    == SOAP Server ==

    Source Code

    1. /**
    2. * Extends SoapServer with wsdl
    3. */
    4. class APIServer extends SoapServer {
    5. /**
    6. * use reflection api to print supported methods
    7. */
    8. public function wsdl() {
    9. $url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
    10. $className = 'APIService';
    11. $messageMethods = '';
    12. $portTypeOperations = '';
    13. $bindingOperations = '';
    14. $class = new ReflectionClass($className);
    15. $methods = $class->getMethods();
    16. foreach($methods as $methodKey => $methodValue) {
    17. if(!$methodValue->isPublic()) continue;
    18. $messageMethodParts = '';
    19. $params = $methodValue->getParameters();
    20. foreach($params as $paramKey => $paramValue) {
    21. $messageMethodParts .= ' <part name="'.$paramValue->name.'" type="xsd:anyType"/>';
    22. }
    23. $messageMethods .= ' <message name="'.$methodValue->name.'Request">
    24. '.$messageMethodParts.'
    25. </message>
    26. <message name="'.$methodValue->name.'Response">
    27. <part name="Result" type="xsd:anyType"/>
    28. </message>';
    29. $portTypeOperations .= ' <operation name="'.$methodValue->name.'">
    30. <input message="tns:'.$methodValue->name.'Request"/>
    31. <output message="tns:'.$methodValue->name.'Response"/>
    32. </operation>';
    33. $bindingOperations .= ' <operation name="'.$methodValue->name.'">
    34. <soap:operation soapAction="urn:xmethods-delayed-quotes#'.$methodValue->name.'"/>
    35. <input>
    36. <soap:body use="encoded" namespace="urn:xmethods-delayed-quotes" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    37. </input>
    38. <output>
    39. <soap:body use="encoded" namespace="urn:xmethods-delayed-quotes" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    40. </output>
    41. </operation>';
    42. }
    43. $s = '<?xml version ='."'".'1.0'."'".' encoding='."'".'UTF-8'."'".' ?>
    44. <definitions name="'.$className.'"
    45. targetNamespace="'.$url.'"
    46. xmlns:tns="'.$url.'"
    47. xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    48. xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    49. xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
    50. xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    51. xmlns="http://schemas.xmlsoap.org/wsdl/">
    52. '.$messageMethods.'
    53. <portType name="'.$className.'PortType">
    54. '.$portTypeOperations.'
    55. </portType>
    56. <binding name="'.$className.'Binding" type="tns:'.$className.'PortType">
    57. <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    58. '.$bindingOperations.'
    59. </binding>
    60. <service name="'.$className.'Service">
    61. <port name="'.$className.'Port" binding="tns:'.$className.'Binding">
    62. <soap:address location="'.$url.'"/>
    63. </port>
    64. </service>
    65. </definitions>';
    66. header("Content-Type: text/xml");
    67. header(sprintf("Content-Length: %d", strlen($s)));
    68. echo $s;
    69. }
    70. }
    Display All


    == SOAP Authentifizierung ==
    Wir werden den eigentlich SOAP Service kapseln. Jeder Aufruf muss einen SOAP Header zur Authentifizierung enthalten.
    Im Beispiel muss ein SOAP Header mit dem Namen "apikey" angegeben werden. Der einzig mögliche Wert im Beispiel ist "hello".
    Diese Stelle kann natürlich durch ein komplexeren Authentifizierungsverfahren ersetzt werden. So könnt ihr auch einige Funktionen gar nicht erlauben.

    Source Code

    1. <?php
    2. /**
    3. * API Service base system with authentification
    4. */
    5. class APIServiceAuth {
    6. private $auth = false;
    7. /**
    8. *
    9. */
    10. public function __construct() {
    11. $this->apiservice = new APIService();
    12. }
    13. /*
    14. * Authentication function
    15. * This is called by the Soap header of the same name. The function name is a Ws-security standard auth tag
    16. * and corresponds to the header tag.
    17. */
    18. public function APIToken($apikey) {
    19. $this->apikey = is_object($apikey) ? $apikey->apikey : $apikey;
    20. if($this->apikey == 'hello') {
    21. $this->auth = true;
    22. } else {
    23. $this->auth = false;
    24. }
    25. }
    26. /**
    27. * wrapper for real api service - checks authentication first
    28. *
    29. * @param function string
    30. * @param arguments mixed[]
    31. */
    32. public function __call($function, $arguments) {
    33. // authenticated
    34. if(!$this->auth) {
    35. $this->mismatchlog($function, $arguments);
    36. throw new SoapFault("Server", "Authentication error.");
    37. }
    38. // function exists
    39. if (method_exists($this->apiservice, $function)) {
    40. return call_user_func_array(array($this->apiservice, $function), $arguments);
    41. }
    42. else {
    43. throw new SoapFault("Server", "Call to undefined Method.");
    44. }
    45. }
    46. }
    Display All


    == SOAP Service ==
    Der SOAP Service bietet die Implementierung aller Funktionen an, die ihr für öffentliche Aufrufe erlauben wollt.

    Source Code

    1. <?php
    2. /**
    3. * API Service
    4. */
    5. class APIService {
    6. /**
    7. * gets foo
    8. */
    9. public function getFoo($param1, $param2) {
    10. return 'hello '.$param1.' / '.$param2;
    11. }
    12. /**
    13. * sets foo
    14. */
    15. public function setFoo($param1, $param2) {
    16. }
    17. }
    Display All


    == http server ==
    Damit das ganze aufrufbar wird, muss nun alles zusammengefügt werden:

    Source Code

    1. <?php
    2. require_once('APIServer.php');
    3. require_once('APIService.php');
    4. require_once('APIServiceAuth.php');
    5. $server = new APIServer(null, array(
    6. 'uri' => 'demo.easy-coding.de')
    7. );
    8. // output wsdl specs
    9. if(isset($_GET['wsdl'])) {
    10. $server->wsdl();
    11. }
    12. // real handler
    13. else {
    14. $server->setClass('APIServiceAuth');
    15. $server->handle();
    16. }
    Display All


    == http client ==
    Der Client ist für unser Beispiel wie folgt zu konfigurieren:

    Source Code

    1. <?php
    2. /*
    3. * Login credentials to be supplied as a SOAP header
    4. * Class used to ensure Soap Head tags in correct format.
    5. */
    6. class SoapHeaderAPIToken {
    7. public $apikey;
    8. /**
    9. *
    10. * @param apikey
    11. */
    12. public function __construct($apikey) {
    13. $this->apikey = $apikey;
    14. }
    15. }
    16. $uri = 'demo.easy-coding.de';
    17. $wsdl = 'http://demo.easy-coding.de/php/soap-server-wsdl-auth/server.php?wsdl';
    18. $location = 'http://demo.easy-coding.de/php/soap-server-wsdl-auth/server.php';
    19. // Set the login headers
    20. $wsu = 'http://schemas.xmlsoap.org/ws/2002/07/utility';
    21. $usernameToken = new SoapHeaderAPIToken('hello');
    22. $soapHeaders[] = new SoapHeader($wsu, 'APIToken', $usernameToken);
    23. $client = new SoapClient($wsdl, array(
    24. "location" => $location,
    25. "uri" => $uri
    26. ));
    27. $client->__setSoapHeaders($soapHeaders);
    28. // access the client
    29. echo $client->getFoo('a', 'b');
    Display All


    == Demo + Download ==
    Die Demo und alle Downloads findet ihr unter
    demo.easy-coding.de/php/soap-server-wsdl-auth/client.php und demo.easy-coding.de/php/soap-server-wsdl-auth/download.zip

    14,400 times viewed