Как использовать веб-службу WCF, которая использует пользовательскую проверку имени пользователя со страницей PHP? - PullRequest
4 голосов
/ 11 июля 2011

Мне трудно использовать безопасный веб-сервис 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>

Ответы [ 2 ]

9 голосов
/ 13 июля 2011

Я решил проблему.Мне пришлось расширить класс «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

0 голосов
/ 11 июля 2011

SOAP немного смешно с аутентификацией (или может быть), я использовал метод из http://www.php.net/manual/en/soapclient.soapclient.php#101503 см. Комментарий от faebu в faebu dot ch 21-Dec-2010 02:58, чтобы сделать именно это несколькораз ... это может помочь

По существу использует CURL для передачи учетных данных аутентификации ... это может / не может работать для вас!

...