2009-07-05 24 views
10

SfondoAutenticazione ASP.NET web app con servizio WCF

Ho un'applicazione web ASP.NET che interagisce con i servizi WCF. L'applicazione web e i servizi WCF sono sotto il mio controllo. L'applicazione Web ASP.NET utilizza un'implementazione personalizzata del modello di provider di appartenenze ASP.NET (con password memorizzate in formato hash) per autenticare gli utenti che accedono all'applicazione Web. Sia l'applicazione Web ASP.NET che i servizi WCF hanno accesso allo stesso database di appartenenza.

Poiché gli utenti forniranno la propria password solo una volta e non voglio dover memorizzare le loro password ovunque o infastidirli ripetutamente chiedendo loro di fornire la loro password, ho bisogno di un meccanismo appropriato per autenticare gli utenti con Servizi WCF.

Sulla base di altre domande e risposte che ho visto, sto considerando una sorta di approccio "sessione di accesso", in cui verrà creata una sessione di accesso nel database di appartenenza personalizzato quando l'utente accede inizialmente all'applicazione Web, con la sessione di accesso identificata da un GUID e scaduta automaticamente dopo un periodo di inattività. Il GUID della sessione di accesso verrà "ricordato" dall'applicazione Web per ciascun utente connesso (memorizzato nel ticket di autenticazione dei moduli o nella sessione).

Il servizio WCF fornirà anche la propria operazione di accesso accettando un nome utente e una password e restituendo un GUID della sessione di accesso come descritto sopra.

Il servizio WCF sarebbe quindi accettare il GUID sessione di login per tutte le altre operazioni, e verificare che il GUID rappresenta una sessione di accesso valido che non è scaduto prima di consentire l'operazione di procedere.

ho fatto un po 'di valori di fondo su questo, e c'è un sacco di materiale sull'uso diretto di tipo credenziali del client UserName, ma ciò richiederebbe l'applicazione web per ricordare la password dell'utente, che non lo fa mi sembra una grande idea.

Ho fatto qualche ricerca e ho trovato materiale su MSDN, ma questo sembra un grande sforzo per implementare quello che (almeno per me) sembra uno scenario di utilizzo piuttosto comune.

How to: Create a Custom Token

Domanda

è l'impostazione generale della "sessione di login" descritto sopra ragionevole?
Se sì, qual è il modo migliore per raggiungerlo?
In caso contrario, puoi suggerire un'alternativa?

+0

è il vostro servizio WCF accessibile da solo rete interna? In tal caso, non vedo la necessità di autenticare nuovamente le richieste. –

+0

Ci scusiamo per l'omissione - il servizio WCF sarà disponibile su Internet. –

risposta

1

Grazie a tutti per il vostro contributo. Ho optato per un approccio (almeno per ora). È abbastanza semplice e funziona bene per i miei scopi.

Utilizzando il clientCredentialType "UserName" e un metodo di accesso al servizio esplicito che restituisce un token di sicurezza (dettagli di generazione di token omessi per brevità), il client di servizio può decidere se passare la password autentica come proprietà password sulle credenziali del client o il token di sicurezza invece (ottenuto dal metodo di login). Se il client è un'applicazione Web, il token di sicurezza potrebbe essere memorizzato nel ticket di autenticazione moduli, o nella sessione, o dovunque.

Utilizzando l'userNamePasswordValidationMode "Custom" e un'implementazione personalizzata di UserNamePasswordValidator, il validatore ispeziona la password per determinare se si tratta di un token di sicurezza valido o una password - se si tratta di una password le credenziali del client vengono autenticati contro l'archivio utente (SQL Database del server), e se si tratta di un token di sicurezza, viene controllato per assicurarsi che sia valido, non sia scaduto e appartenga al nome utente.

1

Ci sono due possibili soluzioni che posso pensare:

In primo luogo, se il servizio WCF è un servizio interno, l'applicazione web può quindi inviare il nome dell'utente che chiede per i dati ad ogni richiesta.

Il secondo è che si memorizzano il nome utente e l'hash della password (o della password effettiva) da qualche parte. O nello stato di sessione o nel cookie utente (un cookie di sessione memorizzato in memoria passato all'utente su https). Quindi passare il nome utente e la password al servizio WCF con ciascuna richiesta.

+1

Il servizio WCF sarà disponibile su Internet. Se memorizzo un hash della password, allora devo abilitare l'autenticazione con il servizio WCF usando l'hash della password - per quanto posso vedere questo rende effettivamente solo una password (anche se sarebbe difficile/impossibile da indovinare), ma comunque qualcosa che sarebbe "permanentemente" utile se compromesso (almeno fino a quando l'utente non modificasse la propria password). Utilizzando l'approccio del token di sessione di accesso che ho originariamente descritto significherebbe che il token di sessione di accesso era valido solo per un breve periodo e sarebbe molto meno rischioso se compromesso. –

1

Vedere la risposta su Storing password in forms authentication cookie - ASP.NET and WCF calls per una soluzione che non richiede la memorizzazione di password.

+0

Avevo letto la risposta che hai indicato prima di pubblicare questa domanda. Sembra un approccio interessante, ma sono un po 'confuso sulla meccanica. Potresti chiarire o fornire un esempio? –

+0

@Secret Squirrel, ho espanso la risposta nell'altra pagina. –

2

Questo è un approccio molto ragionevole.

Per eseguire questa operazione è necessario configurare l'endpoint del servizio e configurarlo con il proprio provider di appartenenza personalizzato (è possibile fare lo stesso con il provider di appartenenze SQL, non è necessario uno personalizzato).

Sull'applicazione Web è possibile impostare l'evento Autentica del controllo di accesso per istanziare un nuovo proxy di servizio e impostare il nome utente/password in ClientCredentials nel proxy.

Ora quando si effettua la chiamata al servizio tramite il proxy WCF passerà queste credenziali attraverso il canale protetto al servizio e le utilizzerà per l'autenticazione.

Ora è sufficiente memorizzare il proxy in sessione e utilizzarlo per l'accesso futuro al servizio in quanto ha lo stato del canale e una chiave privata.

protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e) 
{ 
    bool Authenticated = false; 
    try 
    { 
     MyServiceClient proxy = new MyServiceClient("MyServiceEndpoint"); 
     proxy.ClientCredentials.UserName.UserName = LoginControl.UserName; 
     proxy.ClientCredentials.UserName.Password = LoginControl.Password; 

     //It doesn't really matter what is called or what it does because 
     //Membership Provider for the Service does the authentication. 
     string retval = proxy.login("Logging in"); 

     //Now that channel is established the proxy needs to be kept 
     //since it contains the channel state which includes a private key 
     Session["MyServiceProxy"] = proxy; 
     Authenticated = true; 
    } 
    catch (Exception ex) 
    { 
     //Login Error... 
    } 
    e.Authenticated = Authenticated; 
} 
+0

Penso che il tuo suggerimento sia interessante, ma sono preoccupato di cosa accadrebbe se il canale fosse in errore (errore di comunicazione, eccezione del servizio non gestito, ecc.) - la sessione di applicazione web conterrebbe un riferimento a un proxy morto e non ci sarebbe alcun modo di creare un nuovo proxy poiché non avrei accesso alla password dell'utente. –

+0

Dopo aver riflettuto sul tuo suggerimento, non credo che questo tipo di approccio sarebbe appropriato. L'applicazione Web deve interagire con più servizi WCF (con le stesse credenziali utente) e questo approccio mi richiederebbe di creare un proxy per ogni servizio nel punto in cui l'utente accede e memorizza nella cache tutti questi riferimenti proxy nella sessione. Non penso che questo cambierà bene e ho bisogno di supportare un numero elevato di utenti simultanei su un server condiviso. –

+0

Ogni volta che si crea un'istanza del proxy, è necessario passare attraverso l'handshake per stabilire un canale sicuro. A seconda della configurazione, questo può includere lo scambio di certificati e la generazione e la condivisione di una chiave di crittografia effimera. La memorizzazione nella cache del proxy elimina questo scambio da qualsiasi richiesta. Non sono sicuro di come rispondere alla domanda sul canale in errore poiché non ho testato questo scenario. Se non si ristabilisce automaticamente allora probabilmente dovresti salvare anche il nome utente/password da qualche parte. Non so che avresti molta scelta. – RonnBlack

0

vorrei suggerire di dare un'occhiata a Geneva che mira a risolvere situazioni come la tua. L'idea di base è di richiedere lo stesso token di sicurezza, tramite un HttpModule, sia per i servizi WCF che per il sito ASP. Il token sarà rilasciato dopo l'autenticazione con il tuo database di appartenenza e potrebbe contenere informazioni utili (attestazioni) sull'utente.

Per un'introduzione è possibile leggere Bustamante's article.

+0

Avevo guardato a Ginevra come risultato della lettura dell'articolo di Bustamente un paio di mesi fa, e suona come una possibile soluzione, ma è ancora in beta, e sfortunatamente ho bisogno di una soluzione ora. :-) –

0

Microsoft dispone di un servizio WCF che è possibile utilizzare per autenticare gli utenti con l'abbonamento a ASP.NET.

Il codice è in realtà integrato nel framework - è sufficiente creare un file .svc per utilizzarlo.

http://msdn.microsoft.com/en-us/library/bb398990.aspx

Problemi correlati