11

Dec

La semplicità fatta servizio, WCF & Username+Password

Ciao a tutti

DEMO

capita ancora di trovare soluzioni di sicurezza custom, dove per custom intendo molto spesso poco sicure, a vantaggio della semplicità

comprendo che chi non ama come me WCF odia il .config Sorriso ma in realtà mettere su un sistema sicuro di messaggistica con username e password gestiti a modo nostro, è tutt’altro che difficile

PASSO 1: creiamo il nostro servizio

a) Creo un nuovo progetto “Empty Web Application” e dentro aggiungo un WCF Service con nome di default Service1

b) sostituisco il DoWork autogenerato con un GetString molto semplice:

IService1:

[OperationContract]
string GetString();

Service1:

public string GetString()
{
    return "Ciao :)";
}

 

a questo punto abbiamo il nostro WCF, dobbiamo aggiungere la sicurezza

PASSO 2: creazione del certificato per instaurare un canale sicuro

a) apro il prompt dei comandi di visual studio, nella sottocartella “Visual Studio Tools” nel menù Start

b) lancio “makecert -r -pe -n "CN=Service1Certificate" -sky exchange -sr LocalMachine –ss My”, dove Service1Certificate è il nome del certificato che gli vogliamo dare

c) per vedere il nostro certificato, posso andare in IIS da pannello di controllo, strumenti di amministrazione, nel centro, sotto il gruppo IIS, troverò il link ServerCertificates, lo apro

image

d) da qui posso fare Export con il click destro per esportare il nostro certificato da poi importare sul server di destinazione sempre da questo pannello di IIS

a questo punto abbiamo il certificato

PASSO 3: Aggiungo il validatore nel progetto.

a) aggiungo il riferimento a System.IdentityModel

b) aggiungo una classe che estende UserNamePasswordValidtor (System.IdentityModel.Selectors) ed implemento la classe astratta aggiungendo il nostro codice al metodo Validate. es stupido:

public override void Validate(string userName, string password)
{
    if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
        throw new SecurityTokenException("Username or password not valid!");  //using System.IdentityModel.Tokens
}

a questo punto abbiamo il validatore

 

PASSO 4: Configuro WCF per usare certificato e validatore

Aprendo il web.config, posso configurare entrambe le cose. esempio:



 
   
 

 
   
     
       
         
         
         
           
                                            storeName="My"
                                storeLocation="LocalMachine"
                                x509FindType="FindBySubjectName"/>
           
                                                 customUserNamePasswordValidatorType="UserNamePasswordSimpleService.MyConstomUsernamePasswordValidator, UserNamePasswordSimpleService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
         

       

     

   

   
     
     
       
       
     

   

   
     
       
       
         
           
         

       

     

   

   
 


Il gioco è fatto Sorriso

peccato che sul client avremo problemi perchè il certificato è un certificato locale non valido a livello pubblico… quindi, o al posto di generarlo a mano con il “makecert” lo compriamo (anche gratis ad esempio con SmartSSL), oppure dobbiamo disabilitare il check di sicurezza sul client così da poter usare anche io nostro certificato

PASSO 5: Il Client

Basta fare un nuovo progetto Windows o Console, poi click destro sui riferimenti, e click su “Add Service Reference”, li basta selezionare l’url del nostro servizio che vediamo quando andiamo in Debug sul progetto con il servizio, oppure facendo click destro sul servizio (il file .svc) e poi ViewInBrowser.

una volta connesso il client al servizio, la configurazione la farà tutta WCF per noi, a noi servirà solo impostare username e password quando ci connettiamo così:

var c = new ServiceReference1.Service1Client();
c.ClientCredentials.UserName.UserName = "user";
c.ClientCredentials.UserName.Password = "pass";

PASSO 6 [SOLO X CERTIFICATI DI TEST]: disabilito il check di sicurezza sul client per il certificato lato server. Questo l’App.config del client:



 
   
     
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
            bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
            maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
            allowCookies="false">
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                        enabled="false" />
         
                            realm="" />
                            algorithmSuite="Default" />
         

       

     

   


   
     
       
         
           
             
           

         

       

     

   


   
     
      http://localhost:48844/Service1.svc" binding="wsHttpBinding" behaviorConfiguration="ClientBehavior"
          bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
          name="WSHttpBinding_IService1">
       
         
       

     

   

 

 

per disabilitare il check, fare copiaincolla della parte in alto contrassegnata (il tag behaviors) e poi aggiungere la parola behaviorConfiguration come segnalato in basso nel proprio app.config senza alterare le altre configurazioni

 

 

per ogni dubbio, contattatemi pure Sorriso

info@antonioesposito.it

 

DEMO

by Antonio Esposito on 12/11/2011