2009-07-18 17 views
5

Sto lavorando a un'applicazione web Silverlight v3 e desidero proteggere l'accesso al servizio WCF che sto utilizzando per recuperare i miei dati. Attualmente il WCF funziona correttamente, ma non richiede alcuna credenziale utente.WCF + Credenziali utente

Non ho molta esperienza con questo aspetto di WCF, quindi la mia prima idea era quella di aggiungere i parametri di username e password a ciascuna delle operazioni del mio servizio. Il problema che ho con questo è che questo richiederebbe molto codice ridondante, e il fatto che il nome utente e la password verrebbero trasferiti sul filo in testo normale.

Quello che vorrei è un modo per specificare le credenziali in anticipo sul lato client subito dopo aver creato il mio servizio proxy (sto usando il proxy generato automaticamente da "Aggiungi riferimento servizio").

Dopo aver cercato su google una soluzione, sono riuscito a trovare solo soluzioni simili alla mia prima idea (utilizzando i parametri username/password). Qualcuno potrebbe per favore indirizzarmi nella giusta direzione?

Grazie!

risposta

7

Da dove vengono questi nomi utente e password? Se il proprio sito Web implementa già l'autenticazione basata su form, è possibile ignorare personalmente le credenziali di impostazione e utilizzare il cookie di autenticazione dei moduli.Se i tuoi utenti hanno effettuato l'accesso, il cookie viaggerà con la chiamata al servizio web. Per leggerlo dall'altra parte devi fare un paio di cambiamenti.

Per prima cosa è necessario abilitare la modalità di compatibilità ASP.NET per WCF nella sezione System.ServiceModel:

<system.serviceModel> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
</system.serviceModel> 

Una volta fatto ciò, allora per ogni metodo di servizio si vuole comprendere il cookie ASP.NET aggiungere il [AspNetCompatibilityRequirements] attribuisci alla tua classe di servizio

[ServiceContract] 
[AspNetCompatibilityRequirements(
    RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
public class ExampleService 
{ 
} 

Ora all'interno di ogni metodo è possibile accedere all'oggetto HttpContext.Current.User.Identity per scoprire l'identità dell'utente.

Se desideri solo alcuni metodi di essere chiamato da utenti autenticati quindi è possibile utilizzare un PrincipalPermission così

[OperationContract] 
[PrincipalPermission(SecurityAction.Demand, Authenticated=true)] 
public string Echo() 

Come bonus se si sta utilizzando provider di ruoli di ASP.NET poi quelli saranno anche essere popolato e è possibile quindi utilizzare un PrincipalPermission sui metodi per limitare a membri di un ruolo particolare:

[OperationContract] 
[PrincipalPermission(SecurityAction.Demand, Role="Administators")] 
public string NukeTheSiteFromOrbit() 

E questo lavora a Silverlight2 pure, ovviamente.

+0

Sembra buono; ti capita di sapere se questo (o qualcosa di simile) è utilizzabile se usi httpwebrequest crudo? Ho uno stack RPC personalizzato che vorrei proteggere allo stesso modo (posso ovviamente chiedere come nuovo queston se è una risposta non banale) –

+0

Dovrebbe fare sì; vedi http://www.silverlightshow.net/items/Cookies-in-Silverlight-Web-Requests.aspx – blowdart

+0

Ta; Lo guarderò ;-p –

0

è possibile passare in qualche tipo di oggetto di autenticazione e crittografarlo a livello di messaggio con WCF. Gli aspetti C# (http://www.postsharp.org/) possono quindi essere utilizzati per evitare la logica ridondante. È un modo molto pulito di gestirlo.

1

Non eseguire il rollover e aggiungere parametri espliciti: è davvero troppo lavoro!

Controlla le funzionalità di sicurezza WCF: molte sono disponibili! Puoi ad es. proteggere il messaggio e includere le credenziali all'interno del messaggio: tutto pronto, nessun codice aggiuntivo richiesto!

Dai un'occhiata a questo eccellente articolo sulla sicurezza WCF da Michele Leroux Bustamante: http://www.devx.com/codemag/Article/33342

Nel tuo caso, suggerirei la sicurezza dei messaggi con le credenziali nome utente - è necessario configurare questo su entrambe le estremità:

lato server:

<bindings> 
    <basicHttpBinding> 
    <binding name="SecuredBasicHttp" > 
     <security mode="Message"> 
     <message clientCredentialType="UserName"/> 
     </security> 
    </binding> 
    </basicHttpBinding> 
</bindings> 
<services> 
    <service name="YourService"> 
    <endpoint address="http://localhost:8000/MyService" 
       binding="basicHttpBinding" 
       bindingConfiguration="SecuredBasicHttp" 
       contract="IYourService" /> 
    </service> 
</services> 

Ed è necessario applicare le stesse impostazioni sul lato client:

<bindings> 
    <basicHttpBinding> 
    <binding name="SecuredBasicHttp" > 
     <security mode="Message"> 
     <message clientCredentialType="UserName"/> 
     </security> 
    </binding> 
    </basicHttpBinding> 
</bindings> 
<client> 
    <endpoint address="http://localhost:8000/MyService" 
       binding="basicHttpBinding" 
       bindingConfiguration="SecuredBasicHttp" 
       contract="IYourService" /> 
</client> 

Ora il vostro server e il client sono d'accordo sulla sicurezza - sul client, si sarebbe quindi specificare il nome utente e la password da usare in questo modo:

YourServiceClient client = new YourServiceClient(); 

client.ClientCredentials.UserName.UserName = "your user name"; 
client.ClientCredentials.UserName.Password = "top$secret"; 

Sul lato server, è necessario per impostare il modo in cui vengono convalidate le credenziali dell'utente, in genere contro un dominio Windows (Active Directory) o contro il modello di provider di appartenenze ASP.NET. In ogni caso, se le credenziali dell'utente non possono essere verificate rispetto a quel negozio definito, la chiamata verrà rifiutata.

Spero che questo aiuti un po '- la sicurezza è un grande argomento in WCF e ha un sacco e un sacco di opzioni - si può essere un po' scoraggiante, ma alla fine, di solito ha senso! :-)

Marc

+6

Non sono sicuro dello scenario in cui si è stati in grado di farlo, ma in base alla mia esperienza, questo non è consentito in WCF. Non è possibile utilizzare la sicurezza delle credenziali nome utente in modalità messaggio in basicHttpBinding, non è consentito dal framework poiché le credenziali sarebbero passate in testo normale. Otterrai questa InvalidOperationException: "L'associazione BasicHttp richiede che BasicHttpBinding.Security.Message.ClientCredentialType sia equivalente al tipo di credenziale BasicHttpMessageCredentialType.Certificate per i messaggi protetti. Seleziona Transport o TransportWithMessageCredential security per le credenziali UserName." – Grank

Problemi correlati