2016-11-18 25 views
2

從C#程序中,我試圖調用用Java編寫的WebService。 如果我使用SOAPUI調用WS我可以小提琴手看到,調用如下:從C調用Java WS#

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

那麼怎麼辦我使用用戶名和密碼添加肥皂標題以在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' 未被此郵件的收件人理解,導致郵件未被處理。
此錯誤通常表示此消息的發件人已啓用接收方無法處理的通信協議。 請確保客戶端綁定的配置與服務的綁定一致。

+0

您是否考慮過爲WS購買認證,以便您可以切換到https?那不超過20美元/年.. – Marc

+0

我無法控制WS,並且發佈者告訴我WS上沒有證書或其他安全性(部分用於用戶名和SOAP標頭中的PW) –

回答

1

不幸的是,微軟決定取消對WCF中WSSecurity/UsernameTokens的支持。幾周前,我在同一個問題上苦苦掙扎,我對這個問題進行了一些探討,但是無法找出他們爲什麼這麼做。但是有一點希望,只需要一點點努力。

首先,如果你不想使用HTTPS,你需要指定在綁定(您指定的HTTPS)。例如我的結合(也只使用HTTP)看起來很簡單的像:

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

之後,創建在請求必要的WSS Security頭,我定義我施加在端點上的自定義行爲。此行爲將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增強功能(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」的構造函數中考慮這一點,因爲我正在進行哈希處理。

+0

謝謝, 我會試一下 ! –

+0

好的,祝你好運。讓我更新你的進度,如果你需要一些進一步的幫助/信息。 –

+0

我現在得到的數據,以及在提琴手,在代碼中我得到一個錯誤,請參閱我的問題 –