【问题标题】:Calling a Java WS from C#从 C# 调用 Java WS
【发布时间】:2016-11-18 07:46:39
【问题描述】:

我试图从一个 C# 程序调用一个用 Java 编写的 WebService。 如果我使用 SoapUi 调用 WS,我可以在 fiddler 中看到调用如下所示:

<soap:Envelope xmlns:ser="http://service.webservice.com" xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
       <soap:Header>
           <wsse:Security soap:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"   xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
               <wsse:UsernameToken wsu:Id="UsernameToken-8684DEB94ABXXXXXXXXXX362973">
                   <wsse:Username>MyUserName</wsse:Username>
                   <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MyPassword</wsse:Password>
                   <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">fjwe5h78k7vgheedRv21g==</wsse:Nonce>
                   <wsu:Created>2016-11-17T11:53:56.297Z</wsu:Created>
               </wsse:UsernameToken>
           </wsse:Security>
       </soap:Header>
       <soap:Body>
          <ser:getTrades>
                <ser:filter>
                <ser:fromValueDate>2015-03-23</ser:fromValueDate>
                <ser:toValueDate>2015-03-23</ser:toValueDate>
             </ser:filter>
          </ser:getTrades>
       </soap:Body>
</soap:Envelope>

问题是 VisualStudio 创建的类没有标题选项

// CODEGEN: The optional WSDL extension element 'Policy' from namespace 
'http://schemas.xmlsoap.org/ws/2004/09/policy' was not handled.

那么如何添加带有用户名和密码的 Soap 标头以在 C# 中进行调用?

我也一直在寻找使用 WCF,以及来自 wsdl(这里是部分)

    .
    .
    .
    <wsdl:binding name="TradeRetrieverServiceSOAP12Binding" type="ns0:TradeRetrieverServicePortType">
    <wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" Id="UsernameTokenOverHTTPS">
    <wsp:ExactlyOne>
    <wsp:All>
    <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
    <wsp:Policy>
    <sp:TransportToken>
    <wsp:Policy>
    <sp:HttpsToken RequireClientCertificate="false"/>
    </wsp:Policy>
    </sp:TransportToken>
    <sp:AlgorithmSuite>
    <wsp:Policy>
    <sp:Basic256/>
    </wsp:Policy>
    </sp:AlgorithmSuite>
    <sp:Layout>
    <wsp:Policy>
    <sp:Lax/>
    </wsp:Policy>
    </sp:Layout>
    </wsp:Policy>
    </sp:TransportBinding>
    <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
    <wsp:Policy>
    <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"/>
    </wsp:Policy>
    </sp:SignedSupportingTokens>
    </wsp:All>
    </wsp:ExactlyOne>
    </wsp:Policy>
    .
    .

它创建这个绑定:

    <system.serviceModel>
        <bindings>
          <customBinding>
            <binding name="TradeRetrieverServiceSOAP12Binding">
              <security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport"
                requireDerivedKeys="true" securityHeaderLayout="Lax" includeTimestamp="false">
                <localClientSettings detectReplays="false" />
                <localServiceSettings detectReplays="false" />
              </security>
              <textMessageEncoding messageVersion="Soap12" />
              <httpsTransport />
            </binding>
          </customBinding>
        </bindings>
        <client>
          <endpoint address="http://Myservices/TradeRetrieverService"
            binding="customBinding" bindingConfiguration="TradeRetrieverServiceSOAP12Binding"
            contract="ServiceReference1.TradeRetrieverServicePortType" name="TradeRetrieverServiceSOAP12port_http" />
        </client>
    </system.serviceModel>

但这给了我这个错误:

    The provided URI scheme 'http' is invalid; expected 'https'.
    Parameter name: via

网址是http而不是https

所以我在这里有货。有什么想法吗?

编辑

我现在得到数据,在提琴手中,在代码中我得到这个错误: 来自命名空间“http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”的标头“Security” 此邮件的收件人不理解,导致邮件无法处理。
此错误通常表明此消息的发送方启用了接收方无法处理的通信协议。 请确保客户端绑定的配置与服务的绑定一致。

【问题讨论】:

  • 您是否考虑过为 WS 购买证书以便切换到 https?那不超过20美元/年..
  • 我无法控制 WS,开发人员告诉我 WS 上没有证书或其他安全性(soap header 中的用户名和 PW 部分)

标签: c# web-services wcf soap


【解决方案1】:

遗憾的是,Microsoft 决定删除 WCF 中对 WSSecurity / UsernameTokens 的支持。几周前我在同样的问题上苦苦挣扎,我对这个问题做了一些研究,但不知道他们为什么这样做。但是有希望,只要付出一点努力。

首先,如果你不想使用HTTPS,你需要在绑定中指定(你指定了https)。例如,我的绑定(也只使用 HTTP)看起来很简单:

<customBinding>
  <binding name="dummySoapBinding">
     <textMessageEncoding writeEncoding="UTF-8" messageVersion="Soap11" />
     <httpTransport />
  </binding>
</customBinding>

之后,为了在请求中创建必要的 WSS 安全标头,我定义了一个应用到端点的自定义行为。此行为将 MessageInspector 附加到发送请求的 ClientRuntime。此消息检查器在发送之前更改消息,并添加一个安全标头。你可以找到一些关于自定义行为的信息here。有关消息检查器的信息,请访问here

我的 MessageInspector 当前如下所示:

public string Username { get; set; }

public string Password { get; set; }

public PasswordDigestMessageInspector(string username, string password)
{
    Username = username;
    Password = password;
}

public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
    // do nothing
}

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
    // generate token
    var usernameToken = new UsernameToken(this.Username, this.Password, PasswordOption.SendHashed);

    // save token as xml
    var securityToken = usernameToken.GetXml(new XmlDocument());
    var securityTokenText = securityToken.OuterXml;

    // remove vs data
    var limit = request.Headers.Count;
    for (var i = 0; i < limit; ++i)
    {
        if (!request.Headers[i].Name.Equals("VsDebuggerCausalityData")) continue;

        request.Headers.RemoveAt(i);
        break;
    }

    // set encoding type for nonce
    var nonceRegex = new Regex(@"<wsse:Nonce");
    securityTokenText = nonceRegex.Replace(securityTokenText,
        "<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\"");

    var newDoc = new XmlDocument();
    newDoc.LoadXml(securityTokenText);

    // create security header from message
    var securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", newDoc.DocumentElement, false);

    // add header to request message
    request.Headers.Add(securityHeader);

    // complete
    return Convert.DBNull;
}

我在这里使用的 UsernameToken 类拥有你需要的一切。它在 WCF 之前被及时使用,但遗憾的是已被删除。此类定义在:Microsoft.Web.Services3.Security.Tokens。应该有 nuget 包。或者,您可以手动安装 Microsoft 的 WebService Enhancements (WSE) 3.0 (here)。

还有一些额外的逻辑可以修改一些参数,以便我调用的 WebService 将接受我的请求。它非常严格,我没有选择修改它。你可能可以忽略它。

继续,我添加到端点的行为如下所示:

public class PasswordDigestBehaviour : IEndpointBehavior
{
    public string Username { get; set; }

    public string Password { get; set; }

    public PasswordDigestBehaviour(string username, string password)
    {
        Username = username;
        Password = password;
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
        // do nothing
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new PasswordDigestMessageInspector(this.Username, this.Password));
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
        // do nothing
    }

    public void Validate(ServiceEndpoint endpoint)
    {
        // do nothing
    }
}

非常简单。 最后,您可以将行为附加到您的 WCF 客户端类:

client.Endpoint.Behaviors.Add(new PasswordDigestBehaviour("Testuser", "Testpassword"));

我希望它可以节省你一些时间,因为我最近在这个话题上遇到了很多麻烦。

编辑:我刚刚看到您没有发送散列密码。您必须在“UsernameToken”的构造函数中考虑这一点,因为我正在对其进行哈希处理。

【讨论】:

  • 谢谢,我试试看!
  • 好吧,祝你好运。如果您需要进一步的帮助/信息,请让我了解您的最新进展。
  • 我现在得到数据,在提琴手中,在代码中我得到一个错误,请参阅我的问题
  • 你能调试MessageInspector并发布他生成/修改的XML吗?
  • 当您将我的解决方案标记为答案时,我认为它现在可以工作了吗?也许您可以告诉我们究竟是什么问题以及您是如何解决的,如果将来有人也可能对此有进一步的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多