2013-11-27 5 views
9

Próbuję wykonać bardzo proste, ale bezpieczne uwierzytelnianie użytkownika/hasła za pomocą wcf.Podstawowe uwierzytelnianie dla WCF

Jednak gdy patrzę na wartość ServiceSecurityContext.Current.PrimaryIdentity;, zawiera ona dane uwierzytelniające mojego komputera z systemem Windows i twierdzi, że jest autoryzowana (nawet jeśli nie dokonałem jeszcze żadnej autoryzacji) zamiast nazwy użytkownika i hasła podanego w usłudze.

Moje web.config usługi jest następująca

<?xml version="1.0"?> 
<configuration> 

    <appSettings> 
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> 
    </appSettings> 
    <system.web> 
    <compilation debug="true" targetFramework="4.5" /> 
    <httpRuntime targetFramework="4.5"/> 
    </system.web> 
    <system.serviceModel> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior> 
      <!-- To avoid disclosing metadata information, set the values below to false before deployment --> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> 
      <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> 
      <serviceDebug includeExceptionDetailInFaults="true"/> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="WsHttpBindingConfig"> 
      <security mode="TransportWithMessageCredential"> 
      <transport clientCredentialType="None" /> 
      <message clientCredentialType="UserName" /> 
      </security> 
     </binding> 
     </wsHttpBinding> 

    </bindings> 
    <protocolMapping> 
     <add binding="wsHttpBinding" scheme="http" /> 
    </protocolMapping>  
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 
    </system.serviceModel> 
    <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"/> 
    <!-- 
     To browse web app root directory during debugging, set the value below to true. 
     Set to false before deployment to avoid disclosing web app folder information. 
     --> 
    <directoryBrowse enabled="true"/> 
    </system.webServer> 

</configuration> 

i app.config z aplikacji klienckiej jest następujący

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
    </startup> 
    <system.serviceModel> 
     <bindings> 
      <wsHttpBinding> 
       <binding name="WSHttpBinding_IService1" /> 
      </wsHttpBinding> 
     </bindings> 
     <client> 
      <endpoint address="http://localhost/WcfSecuredService/Service1.svc" 
       binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" 
       contract="ServiceReference1.IService1" name="WSHttpBinding_IService1"> 
      </endpoint> 
     </client> 
    </system.serviceModel> 
</configuration> 

zgłoszę usługi z następującego kodu

ServiceReference1.Service1Client clnt = new ServiceReference1.Service1Client(); 
      clnt.ClientCredentials.UserName.UserName = "peter"; 
      clnt.ClientCredentials.UserName.Password = "grr"; 

      string result=clnt.GetSecuredData(); 

Co robię źle?

Należy pamiętać, że zarówno aplikacja kliencka, jak i usługa działają na tym samym komputerze. Nie wiem, czy tożsamość jest identyczna z maszyną, na której działa ta usługa, czy z tą, która została przekazana klientowi, ponieważ są to te same poświadczenia ...

Przypuszczam, że inne pytanie brzmi: "Jak to zrobić? Dostaję nazwę użytkownika i hasło, które zostały przekazane do usługi? "

Odpowiedz

5

Ja pracowałem to się teraz

Musiałem stworzyć klasę zwyczaj sprawdzania poprawności, które znalazłem tutaj How to: Use a Custom User Name and Password Validator

Musiałem także wprowadzić kilka zmian w sieci.config

<?xml version="1.0"?> 
<configuration> 

    <appSettings> 
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> 
    </appSettings> 
    <system.web> 
    <compilation debug="true" targetFramework="4.5" /> 
    <httpRuntime targetFramework="4.5"/> 
    </system.web> 
    <system.serviceModel> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior> 
      <serviceCredentials> 
      <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService1Secure.Auth,WcfService1Secure" /> 
      </serviceCredentials> 
      <!-- To avoid disclosing metadata information, set the values below to false before deployment --> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> 
      <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> 
      <serviceDebug includeExceptionDetailInFaults="true"/> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="WsHttpBindingConfig"> 
      <security mode="TransportWithMessageCredential"> 
      <transport clientCredentialType="None" /> 
      <message clientCredentialType="UserName" /> 
      </security> 
     </binding> 
     </wsHttpBinding> 

    </bindings> 
    <protocolMapping> 
     <add binding="wsHttpBinding" scheme="https" bindingConfiguration="WsHttpBindingConfig" /> 
    </protocolMapping>  
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 
    </system.serviceModel> 
    <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"/> 
    <!-- 
     To browse web app root directory during debugging, set the value below to true. 
     Set to false before deployment to avoid disclosing web app folder information. 
     --> 
    <directoryBrowse enabled="true"/> 
    </system.webServer> 

</configuration> 

i app.config

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
    </startup> 

    <system.serviceModel> 
     <bindings> 
      <basicHttpBinding> 
       <binding name="BasicHttpBinding_IService1" /> 
      </basicHttpBinding> 
      <wsHttpBinding> 
       <binding name="WSHttpBinding_IService1"> 
        <security mode="TransportWithMessageCredential"> 
         <transport clientCredentialType="None" /> 
         <message clientCredentialType="UserName" /> 
        </security> 
       </binding> 
      </wsHttpBinding> 
     </bindings> 
     <client> 
      <endpoint address="https://localhost/WcfService1Secure/Service1.svc" 
       binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" 
       contract="ServiceReference1.IService1" name="WSHttpBinding_IService1" /> 
     </client> 
    </system.serviceModel> 
</configuration> 

Teraz użytkownik jest weryfikowany na życzenie, a nazwa użytkownika jest dostępna za pomocą

ServiceSecurityContext.Current.PrimaryIdentity;

+0

Próbowałem tego kilka razy, ale nazwa użytkownika otrzymana podczas uzyskiwania dostępu do 'ServiceSecurityContext.Current.PrimaryIdentity' nie wydaje się być używane do uwierzytelniania. czy możesz rzucić tutaj trochę światła? –

2

hi należy dodać metodę, która może przyjąć login i hasło na swojej stronie serwera i przechowywać je w zmiennych lub db
metoda powinna wyglądać następująco

ServiceReference1.Service1Client clnt = new ServiceReference1.Service1Client(); 
clnt.ClientCredentials.UserName.UserName = "peter"; 
clnt.ClientCredentials.UserName.Password = "grr"; 

clnt.SignUp(clnt); 

lub

clnt.SignUp(login,password); 

to, co robisz, może pracować na samodzielnej aplikacji, ale nie w usłudze internetowej Twoje połączenie z usługą metod będzie miało coś w rodzaju:

http://MyService/IMyContract/MyAction1

Nadzieja ta pomoc

+0

Naprawdę nie chciałem podawać poświadczeń ręcznie przy każdym połączeniu. Na pewno powinny one być przekazywane automatycznie przez Service1Client? – coolblue2000

+0

W jaki sposób robisz Wątpię, że zostanie przekazany automatycznie jesteś w środowisku SOAP oznacza, że ​​wszystko jest niepoprawne –

+0

Myślałem, że poświadczenia zostały przekazane w nagłówku mydła przez serwer proxy? W przeciwnym razie, dlaczego w ogóle masz właściwość poświadczeń? Widziałem wiele przykładów tego działa, po prostu wszystkie wydają się używać dostawcy sqlmembership wraz z innymi rzeczami, których nie chcę używać. Chcę tylko uwierzytelnić się przy użyciu nazwy użytkownika i hasła przekazywanych automatycznie przez nagłówki mydeł. – coolblue2000

1

Jeśli używasz instancji PerSession następnie można nazwać pierwszym Uwierzytelnianie na serwerze i na udany utrzymać flagę na serwerze, następnie zaproszenie sprawdzi flagi przed wykonaniem . oznacza to, że klient musi wykonać pierwsze wywołanie metody Authenticate, a następnie wywołać tylko inne metody.

Jeśli nie korzystasz z instancji PerSession, możesz utworzyć własną klasę proxy dla serwera i podczas tworzenia instancji proxy zaakceptuj LoginName/Hasło, które może przekazać w nagłówku każdego połączenia, a po stronie serwera implementuj niestandardowy ServiceAuthorizationManager, może pobrać referencje z OperationContext .Current.IncomingMessageHeaders i sprawdza to.

+0

Jeśli chodzi o instancję niesesjonującą, czy to nie jest to, co scf ma domyślnie robić (stąd własność referencji)? – coolblue2000