如何在 Ruby 中创建 urn:localhost-catalog SOAP 标头?

发布于 2024-12-20 12:41:50 字数 835 浏览 1 评论 0原文

我在 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)缺少参数”。此外,我是否通过正确的凭据或虚假的凭据并不重要。这就是为什么我认为身份验证失败。

希望有人可以帮忙!

I have this (working) example in php:

$usernameToken = new SoapHeaderUsernameToken( $password, $username );
$soapHeaders[] = new SoapHeader("urn:localhost-catalog", 'UsernameToken', $usernameToken);

$client = new SoapClient("my_client_url");
$client->__setSoapHeaders( $soapHeaders );

But I want a client in Ruby. I'm using the savon gem, which can do authentication for you. So far, I have the following method:

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

I can successfully list available actions, but if I try to make a request, the result is always "(SOAP-ENV:Client) Missing parameter". Also, it doesn't matter if I pass correct credentials or fake ones. That is why I believe the authentication fails.

Hope someone can help!

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

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

发布评论

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

评论(2

柠檬心 2024-12-27 12:41:50

使用 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>

希望这会有所帮助!

Using Wireshark sniffer I intercepted SOAP request that your PHP code sends. It looks like this:

<?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>

Here you can see that this code adds ns2 namespace for UsernameToken header.

Then I intercepted SOAP request that sends your Ruby code:

<?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>

You can see the difference - UsernameToken is wrapped into Security element and namespace for UsernameToken is "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"

Your PHP code uses custom authorization and savon does not support it via wsse property. I looked into Savon source code, it uses Akami.wsse and in its code there is no possibility to set namespace. This means you need to manually construct headers. Here is the code in Ruby that generates SOAP request like you possibly need:

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

It generate the following SOAP request:

<?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>

Hope this helps!

み格子的夏天 2024-12-27 12:41:50

要在 Savon 中设置标头,请使用以下表达式:

client.request :wsdl, "getProductGroups" do
    soap.header = { :header_key => "your header goes here",
                    :attributes! => { :attr => "your attribute" }
                  }
    soap.body = { :parent_id => 1 }
end

也许这对您有帮助。

-英石

to set a header in Savon use the following expression:

client.request :wsdl, "getProductGroups" do
    soap.header = { :header_key => "your header goes here",
                    :attributes! => { :attr => "your attribute" }
                  }
    soap.body = { :parent_id => 1 }
end

perhaps that helps you.

-st

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