如何在 PHP 的 SOAP WSDL 中的不同端口之间进行选择?

发布于 2024-09-11 01:05:59 字数 1250 浏览 2 评论 0原文

Amazon AWS SQS WSDL(位于 https:/ /sqs.us-east-1.amazonaws.com/doc/2009-02-01/QueueService.wsdl)列出了具有不同“地址”(靠近文件底部)的多个“端口”,其中指定服务的 HTTP 和 HTTPS 地址。

使用 PHP SOAP 对象:

$aws_ns = 'http://security.amazonaws.com/doc/2007-01-01/';
$sc = new SoapClient('https://sqs.us-east-1.amazonaws.com/doc/2009-02-01/QueueService.wsdl');
$sc->__setSoapHeaders(new SoapHeader($aws_ns, 'AWSAccessKeyId', 'MyAccessKey'));
$action = "ListQueues";
$ts = date('c');
$hash = base64_encode(hash_hmac('sha1', $action.$ts, 'MyPrivateKey', true));
try {
  $rs = $sc->__soapCall($action, array(), NULL, array(
    new SoapHeader($aws_ns, 'Signature', $hash),
    new SoapHeader($aws_ns, 'Timestamp', $ts)
  ));
} catch (SoapFault $f) {
  echo "ERROR: ".$f->faultcode."-".$f->faultstring."\n";
}

运行该代码会出现“错误:aws:Client.RequiresSSL-SSL 连接需要向后兼容的 SOAP 身份验证。”;它使用第一个“端口”(HTTP 端口)来联系 AWS 服务,这是此类身份验证所不允许的。

如果我在 __soapCall 之前添加 $sc->__setLocation('https://queue.amazonaws.com'); (从 WSDL 文件复制并粘贴的 URL)行code>,效果很好,但是我如何告诉 SoapClient 对象使用 WSDL 中的其他端口,而不是将其作为静态字符串提供,以防他们将来更改 HTTPS URL?

The Amazon AWS SQS WSDL (at https://sqs.us-east-1.amazonaws.com/doc/2009-02-01/QueueService.wsdl) lists multiple "ports" with different "addresses" (near the bottom of the file), which specify the HTTP and HTTPS addresses for the service.

Using the PHP SOAP object:

$aws_ns = 'http://security.amazonaws.com/doc/2007-01-01/';
$sc = new SoapClient('https://sqs.us-east-1.amazonaws.com/doc/2009-02-01/QueueService.wsdl');
$sc->__setSoapHeaders(new SoapHeader($aws_ns, 'AWSAccessKeyId', 'MyAccessKey'));
$action = "ListQueues";
$ts = date('c');
$hash = base64_encode(hash_hmac('sha1', $action.$ts, 'MyPrivateKey', true));
try {
  $rs = $sc->__soapCall($action, array(), NULL, array(
    new SoapHeader($aws_ns, 'Signature', $hash),
    new SoapHeader($aws_ns, 'Timestamp', $ts)
  ));
} catch (SoapFault $f) {
  echo "ERROR: ".$f->faultcode."-".$f->faultstring."\n";
}

Running that code gives "ERROR: aws:Client.RequiresSSL-SSL connection required for backward compatible SOAP authentication."; it's using the first "port" (the HTTP one) to contact the AWS service, which isn't allowed with this sort of authentication.

If I add a $sc->__setLocation('https://queue.amazonaws.com'); (URL copied and pasted from the WSDL file) line before the __soapCall, it works out fine, but how can I tell the SoapClient object to use the other port in the WSDL, rather than giving it as a static string, in case they change the HTTPS URL down the road?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

め七分饶幸 2024-09-18 01:06:00

据我所知,没有简单的方法告诉 SoapClient 使用另一种。如果只需将 http 更改为 https,并且所有其他条件都相同,则您可以使用自己的类重写某些方法:

class HttpsPortSoapClient extends Soapclient {
  function __doRequest($request,$location,$action,$version,$one_way = 0 ){
    $locationparts = parse_url($location);
    if(isset($locationparts['scheme']) && $locationparts['scheme'] == 'http'){
      if(function_exists('http_build_url')){
        $location = http_build_url($locationparts,array('scheme'=>'https'));
      } else {
        //the long way around:
        $location = 'https://';
        if(isset($locationparts['user'])){
          $location .= $locationparts['user'];
          if(isset($locationparts['pass']))$location .= ':'.$locationparts['pass'];
          $location .= '@';
        }
        if(isset($locationparts['host']))  $location .= $locationparts['host'];
        if(isset($locationparts['port']))  $location .= ':'.$locationparts['port'];
        if(isset($locationparts['path']))  $location .= $locationparts['path'];
        if(isset($locationparts['query'])) $location .= '?'.$locationparts['query'];
      }
    }
    return parent::__doRequest($request,$location,$action,$version,$one_way);
  }
}

如果方法确实不同,则您 可以可能想要重写 __construct 方法,加载 XML,并清除或删除对“http”端口(而不是“https”端口)的任何引用。不过,它看起来越来越像编写自己的肥皂客户端:)

As far as I know, there's no simple way to tell SoapClient to use the other one. If only the http to https change has to be made, and all other things are equal, you might override some method with your own class:

class HttpsPortSoapClient extends Soapclient {
  function __doRequest($request,$location,$action,$version,$one_way = 0 ){
    $locationparts = parse_url($location);
    if(isset($locationparts['scheme']) && $locationparts['scheme'] == 'http'){
      if(function_exists('http_build_url')){
        $location = http_build_url($locationparts,array('scheme'=>'https'));
      } else {
        //the long way around:
        $location = 'https://';
        if(isset($locationparts['user'])){
          $location .= $locationparts['user'];
          if(isset($locationparts['pass']))$location .= ':'.$locationparts['pass'];
          $location .= '@';
        }
        if(isset($locationparts['host']))  $location .= $locationparts['host'];
        if(isset($locationparts['port']))  $location .= ':'.$locationparts['port'];
        if(isset($locationparts['path']))  $location .= $locationparts['path'];
        if(isset($locationparts['query'])) $location .= '?'.$locationparts['query'];
      }
    }
    return parent::__doRequest($request,$location,$action,$version,$one_way);
  }
}

If the methods DO differ, you might want to override the __construct method, and load the XML, and cleanup or remove any references to the 'http' port instead of the 'https' one. It would look more and more like writing your own soapclient though :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文