2013-01-14 6 views
6

Ho un utente SOAP WCF implementato da Visual Studio 2012 da un WSDL. Il WSDL è stato generato da PeopleTools. L'oggetto base è di tipo System.ServiceModel.ClientBase.Con C#, consumer SOAP WCF che utilizza l'autenticazione di testo normale WSSE?

ho bisogno della richiesta SOAP per assomigliare:

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

Ecco il più vicino si può ottenere:

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

Noterete due problemi:

  • Nessuna credenziale WSSE testo in chiaro . Passa un modulo binario delle credenziali che il servizio non utilizzerà.
  • L'autenticazione è Body, non Header.
  • La richiesta omette InputParameters.

Ecco il codice essenziale 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); 

Non c'è sicurezza a livello di HTTP, e il trasporto è crittografato con SSL. L'autenticazione è basata solo sul messaggio SOAP.

+0

Sembra che il WSDL è male. Se è stato creato di nuovo ai tempi di WSE, è probabile che non sia standard. –

+0

Interessante. Cosa ti fa pensare che il WSDL sia cattivo? –

+0

Il fatto che crei un client non valido e il fatto che appaia dai giorni di WSE. Sta usando SOAP 1.1, per esempio. –

risposta

9

Questa è la richiesta per il token WS-SecureConversation. Viene utilizzato da WSHttpSecurity per impostazione predefinita, a meno che non si modifichi la proprietà EstablishSecurityContext su false. Utilizzare invece questa associazione:

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

Utilizzerà SOAP 1.1 con il token UserName e richiederà il trasporto HTTPS.

Edit:

Per il test senza HTTPS tenta di utilizzare questo legame personalizzato:

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

Grazie. Sembra che 'ClientCredentialType' debba essere un' BasicHttpMessageCredentialType', non un 'MessageCredentialType'. Ora un problema: sto usando HTTP per ora in modo che io possa annusare il conneciton di rete usando Wireshark. C'è un modo per ignorare il comportamento per richiedere HTTPS? Ho studiato la modifica di 'binding.Security.Mode', ma sembra che nessuna delle opzioni lo consenta. –

+0

Grazie, ho corretto il primo esempio e ho aggiunto un'altra opzione per il test senza HTTPS. –

+0

Ooh, questo è davvero vicino! Wireshark mostra che la comunicazione è andata a buon fine, ma a .NET Framework non piace la risposta: "** Il processore di sicurezza non è stato in grado di trovare un'intestazione di sicurezza nel messaggio. Ciò potrebbe essere dovuto al fatto che il messaggio è un errore non protetto o perché esiste un'associazione mancata corrispondenza tra le parti comunicanti. Ciò può verificarsi se il servizio è configurato per la sicurezza e il client non sta utilizzando la sicurezza. ** "Opzioni di ricerca ora ... –

-1

Questo mi sembra come wsHttpBindings con sicurezza di trasporto che utilizza l'autenticazione password di base del nome utente.

Queste linee guardano sbagliato per me:

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

Ecco come mi sarei aspettato di vedere questo configurato nel app o 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> 

Quindi il codice sarebbe simile a questa:

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); 

Potrebbe essere spiegato meglio qui ->http://msdn.microsoft.com/en-us/library/ms733775.aspx

+0

Grazie, ma non utilizzando l'autenticazione di base. Il livello HTTP non ha autenticazione. Inoltre, ottengo un errore quando uso '" basic "' come argomento di 'var service = new ServiceWithBizarreNameFromPeoplesoft()'. Apparentemente, se si passa una singola stringa, si aspetta che sia il nome di un elemento endpoint. Questo sembra essere supportato da http://msdn.microsoft.com/en-us/library/ms574925.aspx. –

Problemi correlati