我在php中有这个(工作)示例:
$usernameToken = new SoapHeaderUsernameToken( $password, $username );
$soapHeaders[] = new SoapHeader("urn:localhost-catalog", 'UsernameToken', $usernameToken);
$client = new SoapClient("my_client_url");
$client->__setSoapHeaders( $soapHeaders );
但我想要一个Ruby客户端。我正在使用savon gem,它可以为您进行身份验证。到目前为止,我有以下方法:
def my_soap_client
client = Savon::Client.new do
wsdl.document = "my_client_url"
end
client.wsse.credentials "usr", "pass" # Adding :digest doesn't seem to help
return client
end
# I make requests like this:
my_soap_client.request :wsdl, "getProductGroups", :parent_id => 1
我可以成功列出可用的操作,但是如果我尝试发出请求,结果总是“(SOAP-ENV:Client)缺少参数”。此外,如果我传递正确的凭据或假的凭证也没关系。这就是为什么我认为身份验证失败。
希望有人可以提供帮助!
答案 0 :(得分:2)
使用Wireshark sniffer我拦截了PHP代码发送的SOAP请求。它看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:examples:helloservice"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns2="urn:localhost-catalog"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Header>
<ns2:UsernameToken>
<Password>pass</Password>
<Username>login</Username>
</ns2:UsernameToken>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:getProductGroups>
<parentId>1</parentId>
</ns1:getProductGroups>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在这里,您可以看到此代码为UsernameToken标头添加了ns2名称空间。
然后我拦截了发送Ruby代码的SOAP请求:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://www.ecerami.com/wsdl/HelloService.wsdl"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-1"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>usr</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
pass
</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</env:Header>
<env:Body>
<wsdl:getProductGroups>
<parentId>1</parentId>
</wsdl:getProductGroups>
</env:Body>
</env:Envelope>
你可以看到区别 - UsernameToken被包装到Security元素中,UsernameToken的名称空间是“http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0的.xsd“
您的PHP代码使用自定义授权,而savon不支持通过wsse属性。我查看了Savon源代码,它使用了Akami.wsse,并且在其代码中没有设置命名空间的可能性。这意味着您需要手动构建标头。以下是Ruby中的代码,它可以生成您可能需要的SOAP请求:
require 'savon'
client = Savon::Client.new do
wsdl.document = "test.wsdl"
end
client.request :wsdl, "sayHello" do
soap.namespaces["xmlns:ns2"] = "urn:localhost-catalog"
soap.header = { "ns2:UsernameToken" =>
{"Password" => "pass", "Username" => "login"}
}
soap.body = { :parent_id => 1 }
end
它生成以下SOAP请求:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://www.ecerami.com/wsdl/HelloService.wsdl"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns2="urn:localhost-catalog">
<env:Header>
<ns2:UsernameToken>
<Password>pass</Password>
<Username>login</Username>
</ns2:UsernameToken>
</env:Header>
<env:Body>
<wsdl:sayHello>
<parentId>1</parentId>
</wsdl:sayHello>
</env:Body>
</env:Envelope>
希望这有帮助!
答案 1 :(得分:0)
在Savon中设置标头使用以下表达式:
client.request :wsdl, "getProductGroups" do
soap.header = { :header_key => "your header goes here",
:attributes! => { :attr => "your attribute" }
}
soap.body = { :parent_id => 1 }
end
也许这会对你有帮助。
-st