由于身份验证错误,Php Soap 请求失败

标签 php authentication soap ws-security

我有点脱离了自己的舒适区。我正在尝试使用 PHP 创建 SOAP 请求,并且使用著名的 KBO API,以下是文档:

https://economie.fgov.be/sites/default/files/Files/Entreprises/CBE/Cookbook-CBE-Public-Search-Webservice.pdf

所以基本上一切都很顺利,但我仍然在与身份验证有关的问题上苦苦挣扎,这使我的整个小框架失败了:

<?php

$endpoint = 'https://kbopub-acc.economie.fgov.be/kbopubws110000/services/wsKBOPub';
$wsdl = 'https://kbopub-acc.economie.fgov.be/kbopubws110000/services/wsKBOPub?wsdl';
$username = 'myusername';
$password = 'mypassword';

$timestamp = gmdate('Y-m-d\TH:i:s\Z');
$nonce = base64_encode(random_bytes(16));
$passwordDigest = base64_encode(sha1($nonce . $timestamp . $password, true));
$header = '
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <wsse:UsernameToken>
        <wsse:Username>' . $username . '</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">' . $passwordDigest . '</wsse:Password>
        <wsse:Nonce>' . $nonce . '</wsse:Nonce>
        <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">' . $timestamp . '</wsu:Created>
    </wsse:UsernameToken>
</wsse:Security>';
$options = array(
    'soap_version' => SOAP_1_1,
    'trace' => true,
    'exceptions' => true,
    'encoding' => 'UTF-8',
    'cache_wsdl' => WSDL_CACHE_NONE,
    'stream_context' => stream_context_create(array(
        'http' => array(
            'header' => 'Authorization: WSSE profile=' . $header,
            'user_agent' => 'PHPSoapClient'
        ),
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false
        )
    ))
);
$context = stream_context_create(array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
    ),
));
$options['stream_context'] = $context;
// $options = array(
//     'soap_version' => SOAP_1_1
// );
$client = new SoapClient($wsdl, $options);

// Set up the request parameters
$enterpriseNumber = '0810.002.854';
$request = array('EnterpriseNumber' => $enterpriseNumber);

// Call the SOAP operation with the request parameters
$response = $client->__soapCall('ReadEnterprise', array($request));

// Get the request and response XML
$requestXML = $client->__getLastRequest();
$responseXML = $client->__getLastResponse();

var_dump($response);

我还遵循了 PHP 日志文件中的一些建议,该文件被编写为使用不同版本的 SOAP 版本:SOAP_1_1 而不是 SOAP_1_2。

我发现真正具有挑战性的是我无法以任何方式调试它;我不知道如何检查错误消息,或者我的错误日志文件中没有任何提示,它只是提到了安全检查,但没有太多。

有人遇到同样的问题吗?

顺便说一句,我遇到的错误如下:

[14-Feb-2023 17:09:24 UTC] PHP Fatal error: Uncaught SoapFault exception: [ns1:SecurityError] A security error was encountered when verifying the message in Stack trace: #0 /Users/mymac/Sites/cboxform/api-call/index.php(55): SoapClient->__soapCall('ReadEnterprise', Array) #1 {main} thrown in /Users/mymac/Sites/cboxform/api-call/index.php on line 55

总长度:

总而言之,我需要一个如下所示的请求:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mes="http://economie.fgov.be/kbopub/webservices/v1/messages" xmlns:dat="http://economie.fgov.be/kbopub/webservices/v1/datamodel">
   <soapenv:Header>
 <mes:RequestContext>
<mes:Id>myid</mes:Id>
<mes:Language>fr</mes:Language>
 </mes:RequestContext>
 </soapenv:Header>
 <soapenv:Body>
 <mes:ReadEnterpriseRequest>
 <dat:EnterpriseNumber>0206231995</dat:EnterpriseNumber>
 </mes:ReadEnterpriseRequest>
 </soapenv:Body>
</soapenv:Envelope>

带有摘要密码的 header ,以及将在 300 秒后过期到此端点的时间戳和随机数:

https://kbopub-acc.economie.fgov.be/kbopubws110000/services/wsKBOPub?wsdl

还有一个用户名。

最佳答案

您用来验证 SOAP 请求的安全 token 似乎存在问题。 请检查timezone格式为UTC(YYYY-MM-DDTHH:MM:SSZ)Nonce应该是为每个生成的随机值请求,且 PasswordDigest 值已正确计算,PasswordDigest(SHA-1 哈希)和 Nonce 的串联值,已创建 时间戳,二进制格式的密码

您还可以尝试打印出timestampnoncepasswordDigest的值,以便于调试

您可以尝试替换以下代码中的第 20 行吗:

$options = array(
    'soap_version' => SOAP_1_1,
    'trace' => true,
    'exceptions' => true,
    'encoding' => 'UTF-8',
    'cache_wsdl' => WSDL_CACHE_NONE,
    'stream_context' => stream_context_create(array(
        'http' => array(
            'header' => 'Authorization: WSSE ' . $header,
            'user_agent' => 'PHPSoapClient'
        ),
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false
        )
    ))
);
$context = stream_context_create(array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
    ),
));

WSSE header 在其后的空格内使用正确的配置文件值

关于由于身份验证错误,Php Soap 请求失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75451297/

相关文章:

Php mongo 查找给定数组的匹配文档

php - 两个相同的字符串,但长度不同。修剪、清洁等

javascript - WordPress:PHP 变量在 JavaScript 中显示为空

authentication - Play Framework 句柄授权而不是身份验证

python-3.x - Python - 通过 SOAP 查询 Solarwinds N-Central 时出错

php - HTML5 Builder - 更改页面和组合框中的奇怪字符

java - HttpClient commons-httpclient摘要认证

c# - 将 TOTP Microsoft 身份验证器用于 ASP.NET MVC

python - 我如何使用 lxml objectify 访问 SOAP 响应中的元素值

java - 有关 Java SOAP DocuSign 的任何文档或代码