Соединение с безопасностью WS защитило веб-сервис с PHP

Решение Swift версии 3:

if string.range(of: regex, options: .regularExpression, range: nil, locale: nil) != nil ...

Решение Swift версии 2:

if string.rangeOfString(pattern, options: .RegularExpressionSearch) != nil ...

Пример - содержит ли эта строка две буквы «о»? ]

Примечание. Если появляется сообщение об ошибке 'String' does not have a member 'rangeOfString', добавьте его перед: import Foundation. Это связано с тем, что Foundation предоставляет методы NSString, которые автоматически соединяются с классом Swift String.

import Foundation

Спасибо Онно Эберхарду за обновление Swift 3.

31
задан Stefan Gehrig 5 June 2009 в 17:38
поделиться

3 ответа

Проблема, похоже, в том, что документ WSDL каким-то образом защищенный (базовая аутентификация - я не думаю, что дайджест-аутентификация поддерживается с помощью SoapClient , поэтому вам не повезет в этом случае) и что SoapClient поэтому не может читать и проанализировать описание услуги.

Прежде всего вы должны попытаться открыть расположение WSDL в своем браузере, чтобы проверить, отображается ли диалоговое окно аутентификации. При наличии диалогового окна аутентификации необходимо убедиться, что SoapClient использует необходимые учетные данные для входа в систему при получении документа WSDL. Проблема в том, что SoapClient будет отправлять только учетные данные, указанные с параметрами логин и пароль (а также с параметром local_cert при использовании сертификат аутентификации) при создании клиента при вызове службы, а не при получении WSDL (см. здесь ). Существует два метода решения этой проблемы:

  1. Добавьте учетные данные для входа в URL-адрес WSDL в вызове конструктора SoapClient

     $ client = new SoapClient (
    https: //. urlencode ($ логин). ':'. urlencode ($ пароль). '@ example.com / WSDL / nameofservice',
     массив (
     'логин' => $ логин,
     'пароль' => $ пароль
     )
    );
    

    Это должно быть самое простое решение - но в PHP Ошибка # 27777 написано, что это тоже не сработает (я не пробовал).

  2. Получить WSDL вручную, используя оболочку HTTP-потока или ext / curl , либо вручную через браузер, либо через wget , например, сохраните его на диске и создайте экземпляр SoapClient со ссылкой на локальный WSDL.

    Это решение может быть проблематичным, если документ WSDL изменяется, поскольку вам необходимо обнаружить изменение и сохранить новую версию на диске.

Если диалоговое окно аутентификации не отображается и вы можете прочитать WSDL в своем браузере, вам следует предоставьте дополнительную информацию, чтобы проверить наличие других возможных ошибок / проблем.

Эта проблема определенно не связана с самой службой, поскольку SoapClient уже давится при чтении документа описания службы перед вызовом самой службы.

РЕДАКТИРОВАТЬ:

Наличие файла WSDL локально - это первый шаг - это позволит SoapClient узнать, как взаимодействовать со службой. Не имеет значения, обслуживается ли WSDL напрямую из местоположения службы, с другого сервера или читается из локального файла - URL-адреса служб закодированы в WSDL, поэтому SoapClient всегда знает, где искать службу. конечная точка.

Вторая проблема заключается в том, что SoapClient изначально не поддерживает спецификации WS-Security , что означает, что вы должны расширить SoapClient для обработки определенные заголовки. Точкой расширения для добавления требуемого поведения может быть SoapClient :: __ doRequest () , который предварительно обрабатывает полезные данные XML перед их отправкой в ​​конечную точку службы. Но я думаю, что для самостоятельной реализации решения WS-Security потребуется приличное знание конкретных спецификаций WS-Security. Возможно, заголовки WS-Security также могут быть созданы и упакованы в XML-запрос с помощью SoapClient :: __ setSoapHeaders () и соответствующих SoapHeader s, но я сомневаюсь, что это сработает, оставляя пользовательское расширение SoapClient как единственная возможность.

Простое расширение SoapClient будет иметь вид

class My_SoapClient extends SoapClient
{
    protected function __doRequest($request, $location, $action, $version) 
    {
        /*
         * $request is a XML string representation of the SOAP request
         * that can e.g. be loaded into a DomDocument to make it modifiable.
         */
        $domRequest = new DOMDocument();
        $domRequest->loadXML($request);

        // modify XML using the DOM API, e.g. get the <s:Header>-tag 
        // and add your custom headers
        $xp = new DOMXPath($domRequest);
        $xp->registerNamespace('s', 'http://www.w3.org/2003/05/soap-envelope');
        // fails if no <s:Header> is found - error checking needed
        $header = $xp->query('/s:Envelope/s:Header')->item(0);

        // now add your custom header
        $usernameToken = $domRequest->createElementNS('http://schemas.xmlsoap.org/ws/2002/07/secext', 'wsse:UsernameToken');
        $username = $domRequest->createElementNS('http://schemas.xmlsoap.org/ws/2002/07/secext', 'wsse:Username', 'userid');
        $password = $domRequest->createElementNS('http://schemas.xmlsoap.org/ws/2002/07/secext', 'wsse:Password', 'password');
        $usernameToken->appendChild($username);
        $usernameToken->appendChild($password);
        $header->appendChild($usernameToken);

        $request = $domRequest->saveXML();
        return parent::__doRequest($request, $location, $action, $version);
    }
}

Для базовой аутентификации WS-Security вам нужно будет добавить следующее к SOAP- header:

<wsse:UsernameToken>
    <wsse:Username>userid</wsse:Username>
    <wsse:Password>password</wsse:Password>                                 
</wsse:UsernameToken>

Но, как я сказал выше: Я думаю, что для того, чтобы это работало, необходимо гораздо больше знаний о спецификации WS-Security и данной сервисной архитектуре.

Если вам нужно решение корпоративного уровня для всего диапазона спецификаций WS- * и если вы можете установить модули PHP, вы можете Стоит взглянуть на WSO2 Web Services Framework для PHP (WSO2 WSF / PHP)

29
ответ дан 27 November 2019 в 21:38
поделиться
$client = new SoapClient("some.wsdl", array('login'    => "some_name",
                                            'password' => "some_password"));

Из документации php

0
ответ дан 27 November 2019 в 21:38
поделиться

У меня есть более простое решение, чем расширение существующей библиотеки soapclient.

Шаг 1: Создайте два класса для создания структуры для заголовков WSSE

class clsWSSEAuth {
    private $Username;
    private $Password;
    function __construct($username, $password) {
        $this->Username=$username;
        $this->Password=$password;
    }
}

class clsWSSEToken {
    private $UsernameToken;
    function __construct ($innerVal){
        $this->UsernameToken = $innerVal;
    }
}

Шаг 2: Создайте переменные Soap для имени пользователя и пароля

$username = 1111;
$password = 1111;

//Check with your provider which security name-space they are using.
$strWSSENS = "http://schemas.xmlsoap.org/ws/2002/07/secext";

$objSoapVarUser = new SoapVar($username, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
$objSoapVarPass = new SoapVar($password, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);

Шаг 3: Создайте объект для класса аутентификации и передайте переменную soap

$objWSSEAuth = new clsWSSEAuth($objSoapVarUser, $objSoapVarPass);

Шаг 4: Создайте SoapVar out объекта класса Auth

$objSoapVarWSSEAuth = new SoapVar($objWSSEAuth, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'UsernameToken', $strWSSENS);

Шаг 5: Создайте объект для класса Token

$objWSSEToken = new clsWSSEToken($objSoapVarWSSEAuth);

Шаг 6: Создайте SoapVar из объекта класса Token

$objSoapVarWSSEToken = new SoapVar($objWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'UsernameToken', $strWSSENS);

Шаг 7: Создайте SoapVar для узла «Безопасность»

$objSoapVarHeaderVal=new SoapVar($objSoapVarWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'Security', $strWSSENS);

Шаг 8: Создайте объект заголовка из security soapvar

$objSoapVarWSSEHeader = new SoapHeader($strWSSENS, 'Security', $objSoapVarHeaderVal,true, 'http://abce.com');

//Third parameter here makes 'mustUnderstand=1
//Forth parameter generates 'actor="http://abce.com"'

Шаг 9: Создайте объект Soap Client

$objClient = new SoapClient($WSDL, $arrOptions);

Шаг 10: Установите заголовки для объекта soapclient

$objClient->__setSoapHeaders(array($objSoapVarWSSEHeader));

Шаг 11: Последний вызов метода

$objResponse = $objClient->__soapCall($strMethod, $requestPayloadString);
7
ответ дан 27 November 2019 в 21:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: