24

我正在尝试使用 PHP 和 SOAP 运行 Web 服务,但到目前为止我得到的只是:

(SoapFault)[2] 消息指出:“SOAP-ERROR:解析 WSDL:无法从“ http://localhost/MyRegistration/login.xml ”加载:无法加载外部实体“ http://localhost/MyRegistration /login.xml "

我尝试将 localhost 更改为 127.0.0.1,但这没有什么区别。login 实际上是一个 wsdl 文件,但如果我将 login.wsdl 放在 SOAPClient 构造函数中,它会改为显示“'看起来我们没有 XML 文档'”。

这是我的 SOAP 客户端代码(register_client.php):

<?php
try
{
    $sClient = new SoapClient('http://127.0.0.1/MyRegistration/login.wsdl');    

    $param1 = $_POST["regname"];
    $param2 = $_POST["regpass1"];

    $response = $sClient->loginVerify($param1, $param2);    

    var_dump($response);
}
catch(SoapFault $e)
{
    var_dump($e);
}
?> 

这是 login.wsdl 文件:

<?xml version="1.0"?>
<definitions name="LoginVal" 
    targetNamespace="urn:LoginVal" 
    xmlns:tns="urn:LoginVal"  
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns="http://schemas.xmlsoap.org/wsdl/">
  <types>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Login">
  <xsd:element name="getName" type="xsd:string" />
<xsd:element name="getPass" type="xsd:string" />
  <xsd:element name="LoginResponse" type="xsd:string" />          
</xsd:schema>           
  </types>

  <message name="loginVerify">
<part name="username" type="tns:getName" />
<part name="password" type="tns:getPass" />
  </message>

  <message name="doLoginResponse">
<part name="return" type="tns:LoginResponse" />
  </message>  

  <portType name="LoginPort">
    <operation name="loginVerify">
  <input message="tns:loginVerify" />
  <output message="tns:doLoginResponse" />
    </operation>
  </portType>

  <binding name="LoginBinding" type="tns:LoginPort">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
  <operation name="loginVerify">
    <soap:operation soapAction="urn:LoginAction" />
    <input>
      <soap:body use="encoded" namespace="urn:Login" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />         
    </input>
    <output>
      <soap:body use="encoded" namespace="urn:Login" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />         
    </output>
  </operation>
  </binding>

  <service name="LoginService">
    <port name="LoginPort" binding="tns:LoginBinding">
  <soap:address location="http://localhost/MyRegistration/register.php" />
    </port>
  </service>

</definitions>

而且我不确定这是否涉及,所以我提供了 SOAP 服务器 register.php 的代码:

<?php
if(!extension_loaded("soap"))
{
    dl("php_soap.dll");
}

ini_set("soap.wsdl_cache_enabled", "0");
$server = new SoapServer("login.wsdl", array('uri'=>'http://127.0.0.1/MyRegistration'))

public function loginVerify($username, $password)
{
    if($_POST["regname"] && $_POST["regemail"] && $_POST["regpass1"] && $_POST["regpass2"] )
    {
        if($_POST["regpass1"] == $_POST["regpass2"])
        {
            $servername = "localhost";
            $username = "root";
            $password = "Hellfire";

            $conn = mysql_connect($servername,$username,"Hellfire")or die(mysql_error());

            mysql_select_db("soap",$conn);

            $sql = "insert into users (name,email,password)values('$_POST[regname]','$_POST[regemail]','$_POST[regpass1]')";

            $result = mysql_query($sql,$conn) or die(mysql_error());

            return "You have registered sucessfully";

            //print "<a href='index.php'>go to login page</a>";
        }
        else return "passwords dont match";
    }
    else return "invalid data";
}

$server->AddFunction("loginVerify");
$server->handle();
?>

如果我提供了不必要的信息,我很抱歉,但我在这方面完全是新手 - 如果有人能指出为什么会产生这个 SOAP 错误,以及我能做些什么来纠正,我将不胜感激它。

我正在使用 WAMP 服务器 2.2 版,带有 mySQL 5.5.24 和 PHP 5.3.13

4

13 回答 13

34

安全问题:此答案禁用安全功能,不应在生产中使用!

迁移到 PHP 5.6.5 后,soap 1.2 不再工作了。所以我通过添加可选的 SSL 参数解决了这个问题。

我的错误:

未能加载外部实体

怎么解决:

// options for ssl in php 5.6.5
$opts = array(
    'ssl' => array(
        'ciphers' => 'RC4-SHA',
        'verify_peer' => false,
        'verify_peer_name' => false
    )
);

// SOAP 1.2 client
$params = array(
    'encoding' => 'UTF-8',
    'verifypeer' => false,
    'verifyhost' => false,
    'soap_version' => SOAP_1_2,
    'trace' => 1,
    'exceptions' => 1,
    'connection_timeout' => 180,
    'stream_context' => stream_context_create($opts)
);

$wsdlUrl = $url . '?WSDL';
$oSoapClient = new SoapClient($wsdlUrl, $params);
于 2015-02-19T16:23:55.260 回答
12

将此代码放在任何 Soap 调用之上:

libxml_disable_entity_loader(false);
于 2016-05-20T02:25:30.683 回答
12

安全问题:此答案禁用安全功能,不应在生产中使用!

尝试这个。为我工作

$options = array(
    'cache_wsdl' => 0,
    'trace' => 1,
    'stream_context' => stream_context_create(array(
          'ssl' => array(
               'verify_peer' => false,
                'verify_peer_name' => false,
                'allow_self_signed' => true
          )
    ));

$client = new SoapClient(url, $options);
于 2018-01-27T20:01:10.627 回答
5

安全问题:此答案禁用安全功能,不应在生产中使用!

使用 php soapClient 得到与 https WSDL URL 类似的响应

SoapFault 异常:[WSDL] SOAP-ERROR:解析 WSDL:无法从...加载

从 PHP 5.5.9-1ubuntu4.21 >> PHP 5.5.9-1ubuntu4.23 更新服务器后,我的客户端机器 osx 10.12.6 / PHP 5.6.30 出现问题,但可以建立 MS Web 服务客户端连接没有问题。

当我尝试加载 WSDL 时,Apache2 的 server_access.log 没有显示任何条目,所以我添加'cache_wsdl' => WSDL_CACHE_NONE以防止客户端 wsdl 缓存,但仍然没有条目。最后,我尝试为每个CURL -i检查的 HEADERS 加载 wsdl,但一切似乎都很好..

libxml_get_last_error()提供了一些见解>SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

所以我在通话中添加了一些 ssl 选项:

$contextOptions = array(
    'ssl' => array(
    'verify_peer' => false,
    'verify_peer_name' => false,
    'allow_self_signed' => true
    ));

$sslContext = stream_context_create($contextOptions);

$params =  array(
    'trace' => 1,
    'exceptions' => true,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'stream_context' => $sslContext
    );

try {
    $proxy = new SoapClient( $wsdl_url, $params );
} catch (SoapFault $proxy) {
    var_dump(libxml_get_last_error());
    var_dump($proxy);
}

就我而言'allow_self_signed' => true,成功了!

于 2018-03-21T22:03:28.430 回答
3

在 register_client.php 上,确保已传递给 SoapClient 的 URL 可从您正在执行代码的机器访问。

$sClient = new SoapClient('http://127.0.0.1/MyRegistration/login.wsdl');    

如果 127.0.0.0 不起作用,您可以尝试使用一些网络 IP 地址并查看。

让我知道它是否仍然无法为您解决,我确实尝试了您的示例并且更改路径(使其在我的开发环境中正确)为我修复了相同的错误。

我很想知道它是否不能为您解决问题。

于 2012-10-16T14:20:49.717 回答
3

我正在使用 selinux 并使用以下 shell 命令(以 root 身份)我能够允许 PHP 进行 SOAP 调用:

sudo setsebool -P httpd_can_network_connect on
于 2019-09-18T05:27:46.070 回答
2

我有同样的问题。

这个 php 设置解决了我的问题:

allow_url_fopen -> 1
于 2014-11-10T21:29:49.427 回答
2

尝试使用 SoapClient 时遇到了类似的问题。一切正常,但在生产中,有时在页面刷新时,我会收到“SoapFault 异常:[WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from ..”错误。

我正在使用参数:

new \SoapClient($WSDL, array('cache_wsdl' => WSDL_CACHE_NONE, 'trace' => true, "exception" => 0)); 

删除所有参数对我有用:

new \SoapClient($WSDL); 
于 2019-04-04T11:24:30.633 回答
2

如果您使用 docker,您可能会因为 OpenSSL 默认安全级别而出错。

您需要较低的 seclevel/etc/ssl/openssl.cnfDEFAULT@SECLEVEL=2toDEFAULT@SECLEVEL=1

或者只是添加到 Dockerfile

RUN sed -i "s|DEFAULT@SECLEVEL=2|DEFAULT@SECLEVEL=1|g" /etc/ssl/openssl.cnf

来源:https ://github.com/dotnet/runtime/issues/30667#issuecomment-566482876

更改后,我可以运行 SoapClient 而无需任何其他选项


您可以通过在容器上运行来验证它

curl -A 'cURL User Agent' -4 https://ewus.nfz.gov.pl/ws-broker-server-ewus/services/Auth?wsdl
于 2020-08-04T12:41:40.297 回答
1

我遇到了同样的问题,我成功添加了:

new \SoapClient(URI WSDL OR NULL if non-WSDL mode, [
    'cache_wsdl' => WSDL_CACHE_NONE, 
    'proxy_host' => 'URL PROXY',
    'proxy_port' => 'PORT PROXY'
]);

希望这有帮助:)

于 2019-11-27T09:50:36.697 回答
0

问题可能在于您没有在 php.ini 文件中启用 openssl 扩展

转到您的 php.ini 文件 end remove ;in line where extension=opensslis

当然,在问题代码中有一部分代码负责检查扩展是否已加载,但可能有些粗心会忘记它

于 2019-09-15T22:56:42.143 回答
0

如果有人遇到同样的问题,一种可能的解决方案是设置bindto流上下文配置参数(假设您从 11.22.33.44 连接到 55.66.77.88):

$context = [
    'socket' => [
        'bindto' => '55.66.77.88'
    ]
];

$options = [
    'soapVersion' => SOAP_1_1,
    'stream_context' => stream_context_create($context)
];

$client = new Client('11.22.33.44', $options);
于 2016-08-08T20:35:52.343 回答
0

在我使用 docker 的情况下,我只是将localhost(或127.0.0.1)更改为172.17.0.1in url。这是使用时 docker 主机的默认 IP

networks:
  my-own-network:
    driver: bridge

在 docker-compose.yml 中。

于 2022-02-03T14:05:16.863 回答