2013-01-14 53 views
6

我有一個WCF SOAP使用者,它由Visual Studio 2012從WSDL實現。 WSDL由PeopleTools生成。基礎對象的類型爲System.ServiceModel.ClientBase使用C#,使用WSSE純文本身份驗證的WCF SOAP使用者?

我需要的SOAP請求類似於:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://xmlns.oracle.com/Enterprise/Tools/schemas"> 
    <soapenv:Header> 
     <wsse:Security soap:mustUnderstand="1" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
      <wsse:UsernameToken> 
       <wsse:Username>[plain text username goes here]</wsse:Username> 
       <wsse:Password>[plain text password goes here]</wsse:Password> 
      </wsse:UsernameToken> 
     </wsse:Security> 
    </soapenv:Header> 
    <soapenv:Body> 
     <sch:InputParameters> 
      <Last_Name>Aren</Last_Name> 
      <First_Name>Cambre</First_Name> 
     </sch:InputParameters> 
    </soapenv:Body> 
</soapenv:Envelope> 

這裏是最接近我們可以得到:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"> 
    <s:Header> 
     <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action> 
     <a:MessageID>urn:uuid:3cc3f2ca-c647-466c-b38b-f2423462c837</a:MessageID> 
     <a:ReplyTo> 
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address> 
     </a:ReplyTo> 
     <a:To s:mustUnderstand="1">http://[internal URL to soap listener]</a:To> 
    </s:Header> 
    <s:Body> 
     <t:RequestSecurityToken Context="uuid-7db82975-2b22-4236-94a1-b3344a0bf04d-1" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust"> 
      <t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType> 
      <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType> 
      <t:KeySize>256</t:KeySize> 
      <t:BinaryExchange ValueType=" http://schemas.xmlsoap.org/ws/2005/02/trust/tlsnego" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">FgMBAFoBAABWAwFQ9IhUFGUO6tCH+0baQ0n/3us//MMXzQA78Udm4xFj5gAAGAAvADUABQAKwBPAFMAJwAoAMgA4ABMABAEAABX/AQABAAAKAAYABAAXABgACwACAQA=</t:BinaryExchange> 
     </t:RequestSecurityToken> 
    </s:Body> 
</s:Envelope> 

你會注意到兩個問題:

  • 沒有明文WSSE憑據。傳遞服務不會使用的憑據的二進制形式。
  • 身份驗證在Body,而不是Header
  • 該請求省略了InputParameters

這裏是至關重要的C#代碼:

var service = new ServiceWithBizarreNameFromPeoplesoft(); 

if (service.ClientCredentials == null) 
    throw new NullReferenceException(); 
service.ClientCredentials.UserName.UserName = "test"; 
service.ClientCredentials.UserName.Password = "password"; 

var binding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential) {Security = new WSHttpSecurity()}; 
service.Endpoint.Binding = binding; 

binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; 
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; 
binding.Security.Mode = SecurityMode.Message; 

var input = new InputParameters { Last_Name = "Cambre", First_Name = "Aren" }; 

var returnData = service.BizarrePeopleSoftNameForMethod(input); 

有沒有HTTP層安全,以及運輸是SSL加密。認證僅基於SOAP消息。

+0

這聽起來像WSDL是壞的。如果它是在WSE的日子裏創建的,那麼它很可能是非標準的。 –

+0

有趣。是什麼讓你認爲WSDL不好? –

+0

事實上,它構建了一個糟糕的客戶端,事實上它似乎來自WSE的日子。例如,它使用SOAP 1.1。 –

回答

9

這是WS-SecureConversation令牌的請求。默認情況下,它被WSHttpSecurity使用,除非您將其EstablishSecurityContext屬性更改爲false。使用此而不是綁定:

var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);  
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; 
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName; 

它將使用SOAP 1.1用戶名令牌,這將需要HTTPS傳輸。

編輯:

對於測試,而HTTPS嘗試使用這個自定義綁定:

var securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement(); 
securityElement.AllowInsecureTransport = true; 

var encodingElement = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8); 
var transportElement = new HttpTransportBindingElement(); 

var binding = new CustomBinding(securityElement, encodingElement, transportElement); 
+0

謝謝。看起來'ClientCredentialType'必須是'BasicHttpMessageCredentialType',而不是'MessageCredentialType'。現在有一個問題:我現在使用HTTP,這樣我就可以使用Wireshark來嗅探網絡連接。有什麼方法可以覆蓋需要HTTPS的行爲嗎?我研究了更改'binding.Security.Mode',但似乎沒有任何選項允許這樣做。 –

+0

謝謝,我修復了第一個示例,並在沒有HTTPS的情況下添加了另外一個測試選項。 –

+0

哦,這真的很接近! Wireshark顯示通信成功,但.NET Framework不喜歡響應:「**安全處理器無法在消息中找到安全標頭,這可能是因爲該消息是不安全的錯誤,或者是因爲存在綁定如果服務配置了安全性並且客戶端沒有使用安全性,則會發生這種情況**「現在調查選項... –

-1

這看起來像我wsHttpBindings與傳輸安全使用基本的用戶名密碼認證。

這些線條看起來我錯了:

binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; 
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; 
binding.Security.Mode = SecurityMode.Message; 

以下是我希望看到這個應用程式或web.config中

<bindings> 
    <wsHttpBinding> 
    <binding name="ws" > 
     <security mode="Transport"> 
     <transport clientCredentialType="Basic" proxyCredentialType="Basic" /> 
     </security> 
    </binding> 
    </wsHttpBinding> 
</bindings> 

<client> 
    <endpoint address="http://www.bla.com/webservice" binding="basicHttpBinding" contract="bla.IService" name="ws" /> 
</client> 

配置然後代碼是這樣的:

var service = new GeneratedProxyClient("basic"); 
service.ClientCredentials.UserName.UserName = "test"; 
service.ClientCredentials.UserName.Password = "password"; 
var input = new InputParameters { Last_Name = "Cambre", First_Name = "Aren" }; 
var returnData = service.BizarrePeopleSoftNameForMethod(input); 

在這裏可以更好地解釋 - >http://msdn.microsoft.com/en-us/library/ms733775.aspx

+0

謝謝,但沒有使用基本認證。 HTTP層沒有認證。另外,當使用''basic''作爲'var service = new ServiceWithBizarreNameFromPeoples()'的參數時,我得到一個錯誤。顯然,如果你傳遞一個單一的字符串,它期望這是一個端點元素的名稱。這似乎是由http://msdn.microsoft.com/en-us/library/ms574925.aspx支持。 –