evitare di colpire DB per autenticare un utente su OGNI richiesta in architettura di app web senza stato?

36

Riepilogo

Una volta che un utente si collega a un sito Web e le sue credenziali nome utente / password sono verificate e viene stabilita una sessione attiva, è possibile evitare di colpire il DB per ogni singola richiesta da quell'utente? Qual è il metodo consigliato per autenticare in sicurezza le richieste successive per la durata della sessione, riducendo al minimo le query DB e altri traffico di rete interno?

Sfondo

In un'architettura di server di applicazioni Web stateless, in cui ogni richiesta non è a conoscenza di alcuna attività precedente dell'utente, sarebbe necessario interrogare il DB su ogni singola richiesta da quell'utente (in genere eseguendo una query sull'ID di sessione archiviato in un cookie e trasferito nell'intestazione della richiesta). Ma cosa succede se alcune informazioni di base sono state crittografate e memorizzate in quel cookie di sessione che aveva informazioni sufficienti per convalidare l'utente per richieste non sensibili e non modificabili? Per tali richieste, è possibile ad esempio criptare e memorizzare l'ID utente e qualcosa che identifichi in modo univoco la propria macchina il più possibile (user-agent + indirizzo IP) nei dati della sessione. La chiave utilizzata per crittografare i dati potrebbe cambiare ogni giorno rendendo difficile per qualsiasi hacker clonare i dati di sessione su un altro computer. Alla scadenza della sessione, è necessario convalidare completamente le credenziali dell'utente. Il fatto è che la più grande minaccia per l'hacking di una sessione di un utente sarebbe stata quella di usare il computer di un utente che non l'aveva lasciato. Non dovrei preoccuparmi di questo e lasciare che un certo livello di memorizzazione nella cache tra i server di app Web e il DB si occupi di accelerare il processo di autenticazione? Anche se può sembrare un'ottimizzazione non necessaria, sembra che un candidato sia maturo per migliorare l'efficienza poiché ogni richiesta richiede questo processo. Grazie per qualsiasi suggerimento!

    
posta onlinespending 22.01.2014 - 00:30
fonte

4 risposte

41

è possibile e questa tecnica è ampiamente utilizzata.

Ha alcuni svantaggi minori rispetto alle sessioni stateful:

  1. Non supporta il logout avanzato. Se un utente fa clic su Esci, il cookie viene cancellato dal proprio browser. Tuttavia, se un utente malintenzionato ha catturato il cookie, può continuare a utilizzarlo fino alla scadenza del cookie.
  2. L'uso di un segreto sul lato server per creare i token crea un singolo punto di errore: se il segreto viene catturato, un utente malintenzionato può impersonare qualsiasi utente.

Decidere se utilizzare sessioni stateless o stateful dipende dalle prestazioni e dai requisiti di sicurezza. Il banking online tende a utilizzare sessioni stateful, mentre un blog occupato tende a utilizzare sessioni senza stato.

Sono necessari alcuni accorgimenti per il tuo schema proposto:

  1. La crittografia del token non lo protegge dalla manomissione. Si desidera utilizzare un Message Authentication Code (MAC) che protegge la manomissione. Puoi inoltre utilizzare la crittografia, ma è meno importante.
  2. Devi includere un timestamp nel token e mettere un limite di tempo sulla loro validità. Da qualche parte circa 15 minuti è ragionevole. Normalmente verrai automaticamente riemesso poco prima del timeout, e in genere la riemissione potrebbe incorrere in un hit del database (anche se ciò può essere evitato)
  3. Non includere l'indirizzo IP dell'utente nel token. Circa il 3% degli utenti cambierà legittimamente l'indirizzo IP durante una sessione Web, a causa di ripristini modem, modifica di hot spot WiFi, proxy di carico bilanciato e altro ancora. Sebbene tu possa includere l'agente utente nel token, non è normale farlo: consideralo una tecnica avanzata da usare se sei sicuro di sapere cosa stai facendo.
  4. Se un utente malintenzionato acquisisce un cookie di sessione, può impersonare quell'utente. Non c'è nulla che tu possa davvero fare. Invece, metti tutti i tuoi sforzi per impedire a un utente malintenzionato di catturare il cookie in primo luogo. Usa SSL, usa il flag "sicuro" dei cookie, correggi tutti i difetti di scripting cross-site, ecc. E chiedi consiglio agli utenti di bloccare il loro schermo quando il loro computer è incustodito.

Spero che questo ti sia d'aiuto. Se qualcosa non è chiaro o hai bisogno di ulteriori informazioni, lascia un commento e vedrò se posso aiutarti ulteriormente.

    
risposta data 22.01.2014 - 11:54
fonte
16

Generalmente, è possibile "memorizzare" informazioni sullo stato sul client, anche informazioni sensibili come i dati di autenticazione; tale memoria viene utilizzata per salvare risorse sul server, ad es. per ridurre al minimo il carico del database. Vedi queste domande precedenti:

In poche parole, ogni volta che si desidera memorizzare alcune informazioni s sul server, per essere consultate se lo stesso client ritorna, è possibile invece inviarlo come cookie al client. Potresti volere la crittografia perché tali informazioni potrebbero essere "private", nel senso che non vuoi mostrarle al cliente stesso. Probabilmente desideri integrità perché non desideri che il client sia in grado di modificare i dati senza il tuo consenso. Quindi vuoi sia la crittografia sia un MAC , o, meglio ancora, una di queste modalità di crittografia che fanno entrambe le cose correttamente (< a href="http://en.wikipedia.org/wiki/Galois/Counter_Mode"> GCM è lo standard spesso citato per questo).

Come genericamente, quando si memorizzano le informazioni di stato sul client e sul client, si perde il controllo sul ciclo di vita di tali informazioni. Il cliente può scegliere di non restituire il cookie, ovvero simulare un nuovo cliente nuovo; inoltre, il client può restituire un vecchio valore del cookie. Se questo è un problema per te dipende dalla tua situazione esatta. Probabilmente vorrai includere nei dati dei cookie un timestamp, permettendoti di riconoscere i valori dei cookie che sono davvero troppo vecchi.

    
risposta data 22.01.2014 - 13:25
fonte
1

Ci sono alcuni modi per raggiungere questo problema (e ho visto questo approccio utilizzato nelle API REST).

  1. Uso di HTTP per autenticarsi e quindi utilizzare l'API stateless.
  2. Utilizzo di un metodo di autenticazione HTTP di base e utilizzo di un tokenID in scadenza in ogni richiesta.

In ogni caso, se hai bisogno di autenticazione e stateless dovrai gestire l'autenticazione nella sessione dell'app. Dopo aver verificato le credenziali, puoi effettivamente eseguire la query del database senza eseguirla di nuovo tramite utente fidato o simile.

Assicurati di non consentire la connessione diretta al database da qualsiasi altro utente rispetto a quello che ti è stato permesso di fare dopo il controllo delle credenziali.

    
risposta data 22.01.2014 - 11:41
fonte
0

Sono sicuro che capisci che per omettere un'autenticazione basata su una precedente autenticazione la tua applicazione web è un'applicazione di sessione. Non è stato autenticato lo stato di sessione? Sappi che stai studiando per avere una sessione; potresti chiederti perché hai richiesto un'applicazione per le sessioni di sessione. Normalmente le persone vogliono applicazioni per le sessioni di sessione per due motivi principali: Le richieste possono essere consegnate a diversi server senza preoccuparsi di alcuna dipendenza tra client e membri di una server farm. Collegamento di memoria quando un numero elevato di utenti accede contemporaneamente. Anche nelle applicazioni di sessione è possibile soddisfare tali requisiti facendo in modo che il server emetta un token firmato crittografato durante l'autenticazione, in modo che altri membri della web farm possano verificare quel token per avere un'idea che l'utente possa essere legittimo. La rappresentazione è ancora possibile perché la richiesta successiva necessita dello stesso token. È possibile includere nei dati token le intestazioni HTTP e gli IP della richiesta per limitare il loro utilizzo, ma i proxy centrali possono ancora utilizzare il token eseguendo NAT e copiando le intestazioni del client. Quindi l'unico modo per rendere invulnerabile l'uomo negli attacchi centrali è proteggere la richiesta di autenticazione da https e lasciare che il client ti invii con le credenziali una chiave generata a caso che verrà utilizzata per decodificare la firma della richiesta, il client in ogni richiesta crittograferà alcuni dati della richiesta come firma. I dati crittografati possono essere l'ID di sessione e un elemento di sequenza da un generatore di sequencer prestabilito. Non utilizzare il semplice incrementato di uno a causa del suo comportamento prevedibile. Come in ogni richiesta, questa firma è diversa dalle firme precedenti, puoi essere certo che il client sia autenticato. Se il generatore di sequencer si incrementa sempre, è possibile memorizzare nella cache l'ultimo elemento utilizzato per effettuare un semplice controllo prima di un controllo completo; trasmettendo agli altri membri della farm l'elemento della sequenza utilizzata all'interno dell'ID di sessione e risponderanno solo se l'elemento non è valido. Una sequenza di elementi non è valida se è stata utilizzata in una precedente richiesta nel server di risposta o se gli elementi successivi della sequenza sono scaduti nella cache. Prevenire la linoleum di memoria è un semplice implementazione di un server SQL per ogni farm membro per rendere persistenti queste informazioni e avere in memoria solo le informazioni utilizzate più di frequente. I dispositivi di rete utilizzati per la comunicazione tra i membri della farm devono essere tutti amministrati dal proprietario dell'applicazione perché la comunicazione non è sicura. Con questa struttura la scalabilità è assicurata.

    
risposta data 22.01.2014 - 19:31
fonte