У меня много времени занимает безопасный веб-сервис WCF с сайта PHP. Мои знания в PHP ограничены, я нашел несколько примеров в Интернете, но не смог заставить их работать.
У меня есть приложение Silverlight, которое также использует этот WebService, и оно отлично работает. Но когда я запускаю сайт PHP, я получаю эту ошибку:
MessageSecurityException: процессору безопасности не удалось найти заголовок безопасности в сообщении. Это может быть связано с тем, что сообщение является необеспеченной ошибкой или потому, что существует связующее несоответствие между общающимися сторонами. Это может произойти, если служба настроена для обеспечения безопасности, а клиент не использует безопасность.
Я также попытался изменить customBinding на basicHttpBinding. Когда я это делаю, пользовательский модуль проверки подлинности пользователя больше не вызывается. Но, используя basicHttpBinding и удаляя проверку валидности на моей службе WCF, «работает» (кроме того, что она небезопасна). Поэтому проблема связана с сообщением о безопасности.
Может ли кто-нибудь дать мне рабочий пример или учебник, который мог бы помочь мне сделать эту страницу PHP?
Вот мой PHP-код:
$options = array( 'soap_version' => SOAP_1_1, 'exceptions' => true, 'trace' => 1, 'cache_wsdl' => WSDL_CACHE_NONE, 'Username' => 'MyUserName', 'password' => 'MyPassword'); $client = new SoapClient('https://UrlToService/Service.svc?wsdl', $options); try { $phpresponse = $client->Get(); print $phpresponse->GetResult->Version; echo "</b><BR/><BR/>"; } catch(Exception $e) { echo "<h2>Exception Error!</h2></b>"; echo $e->getMessage(); echo "<BR/><BR/>"; }
Конфигурация WCF
<behavior name="sslBehavior"> <serviceMetadata httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceCredentials> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyNamespace.ServiceUserNameValidator, MyNamespace" /> </serviceCredentials> <serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" suppressAuditFailure="true" /> </behavior> <customBinding> <binding name="sslCustomBinding"> <security authenticationMode="UserNameOverTransport" includeTimestamp="true" allowInsecureTransport="true"> <localServiceSettings maxClockSkew="00:10:00" /> <localClientSettings maxClockSkew="00:10:00" /> <secureConversationBootstrap /> </security> <textMessageEncoding messageVersion="Soap11" /> <httpsTransport /> </binding> </customBinding> <service behaviorConfiguration="sslBehavior" name="MyNamespace.Services.Service"> <endpoint address="" binding="customBinding" bindingConfiguration="sslCustomBinding" contract="MyNamespace.ServiceContracts.IService" /> <host> <baseAddresses> <add baseAddress="https://UrlToService/Services/" /> </baseAddresses> </host> </service>
Я решил проблему. Мне пришлось расширять класс «SoapHeader» в PHP, чтобы он соответствовал стандарту WS-Security.
Вот решение:
Класс заголовка PHP
class WsseAuthHeader extends SoapHeader { private $wss_ns = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'; function __construct($user, $pass, $ns = null) { if ($ns) { $this->wss_ns = $ns; } $auth = new stdClass(); $auth->Username = new SoapVar($user, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns); $auth->Password = new SoapVar($pass, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns); $username_token = new stdClass(); $username_token->UsernameToken = new SoapVar($auth, SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'UsernameToken', $this->wss_ns); $security_sv = new SoapVar( new SoapVar($username_token, SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'UsernameToken', $this->wss_ns), SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'Security', $this->wss_ns); parent::__construct($this->wss_ns, 'Security', $security_sv, true); } }
Клиентский вызов PHP
$options = array( 'soap_version' => SOAP_1_1, 'exceptions' => true, 'trace' => 1, 'wdsl_local_copy' => true ); $username = "MyUser"; $password = "MyPassword"; $wsse_header = new WsseAuthHeader($username, $password); $client = new SoapClient('https://UrlToService/Service.svc?wsdl', $options); $client->__setSoapHeaders(array($wsse_header)); try { $phpresponse = $client->Get(); print $phpresponse->GetResult->Version; echo "</b><BR/><BR/>"; } catch(Exception $e) { echo "<h2>Exception Error!</h2></b>"; echo $e->getMessage(); }
Надеюсь, это поможет кому-то еще!
Благодаря Крису: подключение к защищенной веб-службе WS-Security с помощью PHP
SOAP немного забавна с помощью аутентификации (или может быть), я использовал этот метод с http://www.php.net/manual/en/soapclient.soapclient.php#101503, см. Комментарий от faebu at faebu dot ch 21- Dec-2010 02:58 за то, что вы делаете именно это несколько раз … это может помочь
По сути использует CURL для передачи учетных данных аутентификации … он может / не может работать для вас!