2009-09-01 11 views
14

Dostałem usługę internetową napisaną w języku Java, której nie mogę wprowadzić. Wymaga uwierzytelnienia użytkownika z podstawowym uwierzytelnieniem, aby uzyskać dostęp do dowolnej z metod. Sugerowanym sposobem interakcji z tą usługą w .NET jest użycie Visual Studio 2005 z zainstalowaną wersją WSE 3.0.Nie można wywołać usługi internetowej z podstawowym uwierzytelnianiem za pomocą WCF

To jest problem, ponieważ projekt już korzysta z Visual Studio 2008 (targetowanie .NET 2.0). Mógłbym to zrobić w VS2005, ale nie chcę powiązać projektu z VS2005 lub zrobić go, tworząc zestaw w VS2005 i włączając to w rozwiązanie VS2008 (które zasadniczo wiąże projekt z 2005 r. Mimo wszelkich przyszłych zmian w zespole). Myślę, że każda z tych opcji skomplikowałaby sytuację nowych deweloperów, zmuszając ich do zainstalowania programu GPW 3.0 i uniemożliwiania projektu użycia 2008 i funkcji w .NET 3.5 w przyszłości ... tj. Naprawdę wierzę w używanie WCF jest drogą do zrobienia.

Szukałem przy użyciu WCF do tego, jednak nie jestem pewien, jak uzyskać usługi WCF, aby zrozumieć, że musi wysyłać nagłówki uwierzytelniania wraz z każdym żądaniem. Otrzymuję 401 błędów, gdy próbuję zrobić cokolwiek z usługą sieciową.

To właśnie mój kod wygląda następująco:

WebHttpBinding webBinding = new WebHttpBinding(); 
ChannelFactory<MyService> factory = 
    new ChannelFactory<MyService>(webBinding, new EndpointAddress("http://127.0.0.1:80/Service/Service/")); 
factory.Endpoint.Behaviors.Add(new WebHttpBehavior()); 
factory.Credentials.UserName.UserName = "username"; 
factory.Credentials.UserName.Password = "password"; 

MyService proxy = factory.CreateChannel(); 
proxy.postSubmission(_postSubmission); 

to będzie działać i rzucać następujący wyjątek:

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm=realm'.

I to ma wewnętrzną wyjątkiem:

The remote server returned an error: (401) Unauthorized.

Wszelkie przemyślenia na temat tego, co może być przyczyną tego problemu, byłyby bardzo mile widziane.

Odpowiedz

26

Pierwsze pytanie: czy jest to usługa Java korzystająca z protokołu SOAP lub REST, którą próbujesz wywołać?

W tej chwili za pomocą "webHttpBinding" używasz podejścia opartego na REST. Jeśli usługa Java jest usługą SOAP, należy zamiast tego zmienić powiązanie na "basicHttpBinding".

IF to usługa SOAP oparty, należy spróbować tego:

BasicHttpBinding binding = new BasicHttpBinding(); 

binding.SendTimeout = TimeSpan.FromSeconds(25); 

binding.Security.Mode = BasicHttpSecurityMode.Transport; 
binding.Security.Transport.ClientCredentialType = 
           HttpClientCredentialType.Basic; 

EndpointAddress address = new EndpointAddress(your-url-here); 

ChannelFactory<MyService> factory = 
      new ChannelFactory<MyService>(binding, address); 

MyService proxy = factory.CreateChannel(); 

proxy.ClientCredentials.UserName.UserName = "username"; 
proxy.ClientCredentials.UserName.Password = "password"; 

Używałem tego z różnych usług internetowych i działa - przez większość czasu.

Jeśli to nie zadziała, musisz dowiedzieć się więcej o tym, czego ta usługa sieciowa Java oczekuje i jak wysłać odpowiednie informacje do niej.

Marc

+0

Marca, Czy możesz mi pokazać jak kodować i config jeśli jest REST na podstawie usługi Java? – rajibdotnet

+2

Właściwość ClientCredentials nie pojawia się dla mnie po wpisaniu proxy. – rajibdotnet

+1

@rajibdotnet: Cóż, kod w pytaniu to w zasadzie to, co musisz nazwać usługą opartą na REST .... jeśli to nie pomaga: proszę ** zadaj własne pytanie **, aby ludzie mogli odpowiedzieć ... –

3

dodam do tego, jak również na podstawie podobnego problemu Właśnie doświadczyłem. Automatycznie wygenerowałem config/proxy za pomocą VS - ale konfiguracja, którą utworzyła, nie zadziałała.

Mimo że tryb bezpieczeństwa = "Transport" został ustawiony prawidłowo, nie ma on ustawienia ClientCredentialType = "Basic". Dodałem do tego moją konfigurację i nadal nie działało. Wtedy rzeczywiście usunął zabezpieczenia wiadomości, że narzędzie stworzone od służby ja stykającej jest SSL + Podstawowe tylko:

<message clientCredentialType="UserName" algorithmSuite="Default" /> 

Voila - to działało.

Nie jestem pewien, dlaczego to miało wpływ na to, że element nie określał poziomu zabezpieczeń wiadomości ... ale tak się stało.

6

Przede wszystkim umieść to w pliku app.config lub web.config. (Nie ma potrzeby, aby to zmienić, jak poruszać się po otoczeniu):

<system.serviceModel> 
     <bindings> 
      <basicHttpBinding> 
       <binding name="BasicHttpBinding_IConfigService"> 
        <security mode="TransportCredentialOnly"> 
         <transport clientCredentialType="Basic"/> 
        </security> 
       </binding> 
      </basicHttpBinding> 
     </bindings> 
     <client> 
      <endpoint address="http://localhost:55283/ConfigService.svc" 
       binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IConfigService" 
       contract="IConfigService" name="BasicHttpBinding_IService" /> 
     </client> 
    </system.serviceModel> 

zmienić atrybut kontrakt z nazwą Namespace.Interface odpowiednio. Uwaga tryb security = TransportCredentialOnly

Teraz programowo zmienić punkt końcowy i przekazać poświadczeń, należy użyć następującego kodu:

  var myBinding = new BasicHttpBinding("BasicHttpBinding_IConfigService"); 
      var myEndpoint = new EndpointAddress("http://yourbaseurl/configservice.svc"); 
      var myChannelFactory = new ChannelFactory<IConfigService>(myBinding, myEndpoint); 

      var credentialBehaviour = myChannelFactory.Endpoint.Behaviors.Find<ClientCredentials>(); 
      credentialBehaviour.UserName.UserName = @"username"; 
      credentialBehaviour.UserName.Password = @"password"; 

      IConfigService client = null; 

      try 
      { 
       client = myChannelFactory.CreateChannel(); 
       var brands = client.YourServiceFunctionName(); 
       ((ICommunicationObject)client).Close(); 
      } 
      catch (Exception ex) 
      { 
       if (client != null) 
       { 
        ((ICommunicationObject)client).Abort(); 
       } 
      } 
+0

Nie rozumiem, w jaki sposób wniosek o poświadczenie jest stosowany do kanału? Wygląda na to, że po prostu Znajdź <> poświadczenia klienta i zastosuj go do nowego poświadczenia VarBehavior. Następnie ustawiasz nazwę użytkownika i hasło tej zmiennej ... Jeśli się nie mylę, nie ma to nic wspólnego z powiązaniami lub – SoftwareSavant

Powiązane problemy