it-swarm.dev

evitare di colpire DB per autenticare un utente su OGNI richiesta nell'architettura di app Web senza stato?

Sintesi

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

Background

In un'architettura server di app Web senza stato, in cui ogni richiesta non è a conoscenza di alcuna attività precedente da parte dell'utente, sarebbe necessario interrogare il DB su ogni singola richiesta dell'utente (in genere eseguendo una query sull'ID sessione memorizzato in un cookie e trasferito nell'intestazione della richiesta). E se alcune informazioni di base fossero crittografate e archiviate in quel cookie di sessione che aveva abbastanza informazioni per convalidare l'utente per richieste non sensibili e non modificabili? Per tali richieste, è possibile ad esempio crittografare e memorizzare l'ID utente e qualcosa che identifichi il più possibile in modo univoco la sua macchina (user-agent + indirizzo IP) nei dati della sessione. La chiave utilizzata per crittografare i dati potrebbe cambiare quotidianamente, rendendo difficile per qualsiasi hacker clonare i dati della sessione su un altro computer. Alla scadenza della sessione, è necessario convalidare completamente le credenziali dell'utente. Il fatto è che la più grande minaccia all'hacking della sessione di un utente sarebbe quella di qualcuno che usa il computer di un utente che ha lasciato incustodito. Non dovrei preoccuparmi di questo e lasciare che un certo livello di memorizzazione nella cache tra i server delle app Web e il DB si occupi di accelerare il processo di autenticazione? Sebbene possa sembrare un'ottimizzazione non necessaria, sembra un candidato maturo per miglioramenti in termini di efficienza poiché ogni richiesta richiede questo processo. Grazie per eventuali suggerimenti!

38
onlinespending

è possibile e questa tecnica è ampiamente utilizzata.

Ha alcuni inconvenienti minori rispetto alle sessioni stateful:

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

La decisione di utilizzare sessioni stateless o stateful dipende dalle prestazioni e dai requisiti di sicurezza. L'online banking tenderebbe ad utilizzare sessioni con stato, mentre un blog impegnato tenderebbe a utilizzare sessioni senza stato.

Sono necessarie alcune modifiche al tuo schema proposto:

  1. La crittografia del token non lo protegge dalla manomissione. Si desidera utilizzare un codice di autenticazione dei messaggi (MAC) che protegge la manomissione. È inoltre possibile utilizzare la crittografia, ma è meno importante.
  2. Devi includere un timestamp nel token e fissare un limite di tempo alla loro validità. Da qualche parte circa 15 minuti è sensato. Normalmente si riemettere automaticamente poco prima del timeout e di solito la riemissione incorrerebbe in un hit del database (anche se anche questo 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 del modem, modifica degli hot spot WiFi, caricamento di proxy bilanciati e altro. Sebbene sia possibile includere l'agente utente nel token, non è normale farlo: consideralo una tecnica avanzata da utilizzare se sei sicuro di sapere cosa stai facendo.
  4. Se un utente malintenzionato acquisisce un cookie di sessione, può impersonare tale utente. Non c'è niente che tu possa davvero fare. Invece, fai tutto il possibile per impedire a un utente malintenzionato di acquisire il cookie in primo luogo. Usa SSL, usa il flag di cookie "sicuro", correggi tutti i difetti di scripting cross-site, ecc. E ricevi alcuni consigli dagli utenti per bloccare lo schermo quando il loro computer è incustodito.

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

42
paj28

Generalmente, è possibile "memorizzare" informazioni sullo stato sul client, anche informazioni sensibili come i dati di autenticazione; tale archiviazione viene utilizzata per risparmiare 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, da cercare se lo stesso client ritorna, è possibile invece inviarlo come cookie al client. Potresti desiderare crittografia perché tali informazioni potrebbero essere "private", nel senso che non vuoi mostrarle al cliente stesso. Probabilmente vuoi integrità perché non vuoi che il cliente sia in grado di modificare i dati senza il tuo consenso. Quindi vuoi sia la crittografia che un MAC , o, meglio ancora, una di queste eleganti modalità di crittografia che fanno entrambe correttamente ( GCM essendo lo standard spesso citato per questo).

Come in generale, quando si memorizzano informazioni sullo stato sul client e sul client, si perde un certo controllo sul ciclo di vita di tali informazioni. Il cliente può scegliere di non rispedire il cookie, ovvero simulare un nuovo client aggiornato; inoltre, il cliente può restituire un vecchio valore di 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.

16
Thomas Pornin

Esistono alcuni modi per ottenere questo problema (e ho visto questo approccio usato in REST).

  1. Utilizzo di HTTP per autenticare e quindi utilizzare l'API senza stato.
  2. Utilizzando un metodo di autenticazione HTTP di base e utilizzare un tokenID in scadenza in ogni richiesta.

In ogni caso, se hai bisogno di autenticazione e apolide, dovrai gestire l'autenticazione nella sessione dell'app. Dopo aver verificato le credenziali, è possibile effettivamente eseguire la query del database senza crearla nuovamente tramite un utente attendibile o simile.

Assicurarsi di non consentire la connessione diretta al database da nessun altro utente diverso da quello a cui è stato permesso di farlo dopo il controllo delle credenziali.

1
kiBytes

Sono sicuro che capisci che omettere un'autenticazione basata su un'autenticazione precedente rende l'applicazione Web un'applicazione di sessione. Non è stato autenticato uno stato di sessione? Sappi che stai studiando per avere una sessione; potresti chiederti il ​​motivo per cui hai richiesto una domanda di licenza per le sessioni. Normalmente le persone desiderano applicazioni per i file di sessione per due motivi principali: Le richieste possono essere inviate a server diversi 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 quando l'autenticazione in modo che altri membri della Web farm possano verificare quel token per avere un'idea che l'utente potrebbe essere legittimo. La rappresentazione è ancora possibile perché la seguente richiesta richiede lo stesso token. È possibile includere nei dati token dalle intestazioni e dagli IP http della richiesta per limitarne l'utilizzo ma i proxy medi possono comunque utilizzare il token facendo NAT e copiando le intestazioni del client. Quindi l'unico modo per rendere invulnerabile a man in the middle attacchi è proteggendo la richiesta di autenticazione da https e consentendo al client di inviarti con le credenziali una chiave generata casualmente che verrà utilizzata per decrittografare la firma della richiesta, il client in ciascuna richiesta crittograferà alcuni dati della richiesta come firma. I dati crittografati possono essere l'ID sessione e un elemento 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 sicuro che il client è autenticato. Se il generatore di sequencer è in costante aumento, puoi memorizzare l'ultimo elemento utilizzato per effettuare un controllo semplice prima di un controllo completo; trasmettere gli altri membri della fattoria t della sequenza utilizzata all'interno dell'ID sessione e risponderanno solo se l'elemento non è valido. Una sequenza di elementi non è valida se è stata utilizzata nella richiesta precedente nel server di risposta o se gli elementi successivi della sequenza scadono nella cache. Prevenire il linaggio della memoria è semplice implementare un server SQL per ogni farm membro per rendere persistenti queste informazioni e avere in memoria solo le informazioni utilizzate più frequentemente. I dispositivi di rete utilizzati per la comunicazione tra i membri della farm devono essere tutti amministrati dal proprietario dell'applicazione poiché la comunicazione non è sicura. Con questa struttura è assicurata la scalabilità.

0
Oscar Gras