2013-01-14 24 views
6

Mam konsumenta SOAP WCF, który jest implementowany przez Visual Studio 2012 z WSDL. WSDL został wygenerowany przez PeopleTools. Obiekt podstawowy jest typu System.ServiceModel.ClientBase.Z C#, klientem SOAP WCF, który używa uwierzytelniania zwykłego tekstu WSSE?

muszę żądania SOAP przypominać:

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

Oto najbliżej możemy dostać:

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

Zauważysz dwa problemy:

  • Brak zwykłego tekstu poświadczenia WSSE . Przekazuje binarny formularz poświadczeń, których usługa nie będzie używać.
  • Uwierzytelnianie jest w Body, a nie Header.
  • Żądanie pomija InputParameters.

Oto niezbędne kod 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); 

Nie ma bezpieczeństwa warstwa HTTP, a transport jest szyfrowane protokołem SSL. Uwierzytelnianie opiera się tylko na komunikacie SOAP.

+0

Brzmi jak WSDL jest złe. Jeśli został stworzony w czasach GPW, to może być niestandardowy. –

+0

Interesujące. Co sprawia, że ​​uważasz, że WSDL jest złe? –

+0

To, że buduje złego klienta i fakt, że wydaje się być z czasów GPW. Na przykład używa protokołu SOAP 1.1. –

Odpowiedz

9

To jest żądanie dla tokena WS-SecureConversation. Używa go domyślnie WSHttpSecurity, chyba że zmienisz jego własność na na false. Użyj tego wiązania zamiast:

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

Będzie używać SOAP 1.1 z tokenem NazwaUżytkownika i będzie wymagać transportu HTTPS.

Edit:

Do testowania bez HTTPS spróbować użyć tego wiązania zwyczaj:

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

Dzięki. Wygląda na to, że 'ClientCredentialType' musi być' BasicHttpMessageCredentialType', a nie 'MessageCredentialType'. Teraz jeden problem: używam na razie protokołu HTTP, dzięki czemu mogę wykryć połączenie sieciowe za pomocą Wireshark. Czy istnieje sposób na zastąpienie zachowania wymagającego HTTPS? Sprawdziłem zmianę 'binding.Security.Mode', ale wygląda na to, że żadna z opcji na to nie zezwoli. –

+0

Dzięki, poprawiłem pierwszy przykład i dodałem jeszcze jedną opcję do testowania bez HTTPS. –

+0

Ooh, to jest naprawdę blisko! Wireshark pokazuje, że komunikacja się powiodła, ale system .NET Framework nie lubi odpowiedzi: "** Procesor zabezpieczeń nie mógł znaleźć nagłówka zabezpieczeń w komunikacie. Może to być spowodowane tym, że wiadomość jest niezabezpieczoną usterką lub z powodu powiązania niedopasowanie między stronami komunikacyjnymi może się zdarzyć, jeśli usługa jest skonfigurowana pod kątem bezpieczeństwa, a klient nie korzysta z zabezpieczeń. ** "Zbadanie opcji teraz ... –

-1

To wygląda na mnie jak wsHttpBindings z zabezpieczeniami Transport przy użyciu podstawowego uwierzytelniania hasła użytkownika.

te linie wyglądają źle do mnie:

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

Oto jak byłoby oczekiwać, aby zobaczyć ten skonfigurowana w aplikacji lub 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> 

Następnie kod będzie wyglądać następująco:

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

Tutaj można lepiej wyjaśnić ->http://msdn.microsoft.com/en-us/library/ms733775.aspx

+0

Dzięki, ale nie przy użyciu podstawowego uwierzytelniania. Warstwa HTTP nie ma uwierzytelnienia. Ponadto pojawia się błąd podczas używania '" basic "' jako argumentu 'var service = new ServiceWithBizarreNameFromPeoplesoft()'. Wygląda na to, że jeśli przekażesz pojedynczy ciąg, oczekuje się, że będzie to nazwa elementu punktu końcowego. Wygląda na to, że jest wspierane przez http://msdn.microsoft.com/en-us/library/ms574925.aspx. –