php - manager - set in session laravel




Il driver di sessione del cookie non salverà alcun errore di convalida o dati flash (2)

Il browser ha una limitazione di cookie. È troppo grande per il browser per memorizzare il cookie mentre si utilizza il cookie come driver di sessione. Puoi controllare la limitazione dei cookie del browser qui http://browsercookielimits.squawky.net/

Raccomandazione :
Usa redis come driver di sessione.

Passi :
1.Dopo aver installato il server Redis , aggiungere il pacchetto predis/predis :

composer require predis/predis

2. Cambia il tuo file di configurazione config/database.php :

'redis' => [

    'client' => 'predis',

    'default' => [
        'host' => env('REDIS_HOST', 'localhost'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => 0,
    ],

],

Sto attraversando un periodo difficile con il driver della sessione di cookie in Laravel.

Ho una forma semplice con una validazione in atto. Questo è il mio metodo per salvare i dati di questo modulo:

public function store()
{
    $this->validate(request(), [
        'name'        => 'required',
        'title'       => 'required',
        'description' => 'required|max:600',
        'image'       => 'required|file|mimes:jpeg,png',
    ]);

    $member = TeamMember::create(request()->all());
    $member->addImage(request()->file('image'));

    return redirect()->route('backoffice.team-members');
}

Abbastanza semplice.

Il problema è che, quando si utilizza il driver di sessione cookie, se si salva questo modulo con una descrizione lunga 1024 caratteri, verrà reindirizzato indietro senza dati flash e senza $errors nella vista per la successiva richiesta da gestire.

Esempio:

Questo è un POST dopo aver usato questa linea:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce gravida eros ut leo commodo luctus. Nulla neque dui, laoreet quis felis in, porta tincidunt felis. Phasellus in lacus et sem condimentum ornare. Praesent vitae nisi tempus, gravida tortor eu, convallis dui. Cras lacinia posuere scelerisque. Vestibulum tincidunt purus id sollicitudin varius. Sed eros urna, mattis nec nunc eu, finibus suscipit ipsum. Aliquam varius faucibus congue. Vivamus convallis imperdiet sem a commodo. Proin cursus feugiat sem a pharetra. Curabitur rhoncus non quam sit amet lacinia. Sed ut nisl id odio faucibus vehicula vel ut erat. Vestibulum ut iaculis magna. Quisque sit amet massa sodales, suscipit nisl eu, dapibus elit. Morbi posuere ligula pretium commodo semper. Nam odio elit, rutrum finibus tortor eget, viverra viverra metus. Proin tincidunt tempor ex pretium rhoncus. Proin egestas erat sed eros congue, mollis gravida magna bibendum. Pellentesque vel bibendum nunc. Orci varius natoque penatibus et magnis dis viverra fusce.

Nel campo della descrizione 1024 byte per essere precisi.

Invece, se riempo il campo con altri dati fittizi ma niente di troppo pazzo:

Se cambio il driver di sessione in un file:

... Funziona.

Ma questo non risolve il mio problema. Ho bisogno di utilizzare il driver dei cookie per la sessione poiché il sito Web di produzione è in esecuzione in 3 diversi datacenter per ottenere un'elevata disponibilità. L'utilizzo del cookie per la sessione consente all'utente di colpire uno dei 3 server e continuare comunque con la sua richiesta senza dover utilizzare alcuna sessione adesiva o alcun driver di sessione centrale.

Usare il database come un driver, che è anche in un cluster con HA, non è un'opzione in quanto si tratta di un sito Web con traffico molto elevato e che sarebbe una scrittura per richiesta che non sembra affatto attraente. Vorrei impedirlo ad ogni costo.

C'è comunque questo può essere risolto?

Devo dire che questo è il backoffice del sito web, ma presto l'utente nel frontend sarà in grado di scrivere anche più di 1024 caratteri in una textarea ... quindi se cambio solo il driver per il backoffice non aiuta, come ci imbatteremo nello stesso modo per i nostri utenti.


Il driver della sessione del cookie non è adatto per le applicazioni che devono memorizzare una quantità significativa di dati nella sessione dell'utente. I browser in genere limitano i dati memorizzati in un cookie a circa 4 KB (4096 byte). Come abbiamo visto, possiamo facilmente esaurire questa capacità tentando di memorizzare una stringa di 1024 caratteri nel cookie di sessione: la stringa "Lorem ipsum ..." nella domanda contiene solo caratteri ASCII e ogni carattere ASCII è rappresentato usando 4 byte, quindi 1024 × 4 = 4096 byte.

Come possiamo vedere, iniziamo rapidamente a esaurire lo spazio quando è necessario archiviare elementi aggiuntivi in ​​un cookie di sessione, come i metadati di serializzazione per i valori PHP o quando i dati contengono caratteri UTF-8 che consumano più di 4 byte per carattere. Per continuare a utilizzare i cookie per archiviare dati di sessione superiori a 4 KB, è necessario scrivere un driver di sessione personalizzato che divida i dati della sessione su più cookie per ogni risposta e li riassembli su ogni richiesta. Per una buona ragione, nessun pacchetto esistente fa ciò di cui sono a conoscenza. Questo mi porta al mio prossimo punto ...

Voglio fortemente scoraggiare l'uso dei cookie per l'archiviazione di una sessione completa (anziché solo un ID di sessione). Questo approccio può esporre vulnerabilità di sicurezza, aggiungere sovraccarico a richieste e risposte (comprese richieste di risorse statiche nello stesso dominio), rischiare di desincronizzare i dati (fare clic con il tasto destro del mouse sulla scheda App → Duplicare per vedere cosa succede), complicare i test e il debug e causare problemi quando si memorizzano determinati tipi di dati.

Per l'applicazione distribuita nella domanda, abbiamo quattro opzioni:

  1. Archiviare i dati di sessione su un server centrale a cui accede ogni istanza dell'applicazione
  2. Memorizza lo stato della sessione su ciascun sito e replicalo tra i siti
  3. Utilizzare sessioni "persistenti" per ancorare un utente a un sito dopo aver avviato una sessione
  4. Scrivi una quantità di codice non banale per implementare un driver di sessione personalizzato che permetta al client di passare lo stato della sessione senza utilizzare i cookie, o quello con i cookie delle partizioni

Penso che possiamo ragionevolmente eliminare la quarta opzione. A meno che non abbiamo una buona ragione per evitare di utilizzare i primi tre approcci e di solito non lo facciamo per applicazioni tipiche, non possiamo giustificare la quantità di lavoro, complessità e sovraccarico necessari per costruire un sistema per trasferire i dati di sessione avanti e indietro attraverso HTTP quando le prime tre opzioni sono soluzioni standard e ampiamente accettate.

Sulla base delle informazioni contenute nella domanda, mi sembra che tu abbia già compreso i concetti e le implicazioni dietro le altre tre opzioni, quindi non approfondirò le spiegazioni per ciascuna di esse (ma commentami per farmi sapere se dovrei).

Per le applicazioni senza requisiti di infrastruttura avanzati, raccomando il terzo approccio: sessioni adesive . Queste sono relativamente facili da configurare e in genere richiedono la configurazione sul servizio di bilanciamento del carico in modo che, una volta che un client avvia una sessione con un server delle applicazioni, il bilanciamento del carico instradi le richieste successive allo stesso server fino al termine della sessione. Per la disponibilità elevata, possiamo combinare questo approccio con il driver di sessione Redis e con i server Redis configurati per la replica master-slave tra i data center e, facoltativamente, con Redis Sentinel per automatizzare il failover. Redis si adatta bene ai dati di sessione e offre prestazioni migliori rispetto a un database relazionale. Se disponiamo di più istanze di applicazioni in ciascun data center, Redis fornisce una posizione centrale per i dati di sessione per tutte le istanze in un unico sito.

Per completezza e per rispondere direttamente alla domanda, ecco una panoramica dello sviluppo necessario per creare un driver di sessione basato su cookie che gestisca dati di sessione superiori a 4 KB. Ancora una volta, raccomando uno degli altri approcci descritti sopra:

  • Innanzitutto, dovremo creare una nuova classe che implementa la SessionHandlerInterface di PHP (controlla il gestore della sessione di cookie di Laravel per un punto di partenza, probabilmente possiamo estendere questa classe).

  • Il metodo write() di questa classe dovrà serializzare la sessione $data e quindi dividere i dati in blocchi più piccoli di 4 KB (per alcuni browser, meno di 4093 byte). Assicurati di tenere conto dei caratteri multibyte. Prima di suddividere i dati, potremmo anche voler crittografarli se la sessione contiene informazioni riservate o se non vogliamo che gli utenti intelligenti facciano i conti con i valori. Quindi, il metodo dovrebbe aggiungere un nuovo cookie per ogni blocco dei dati della sessione. Ogni cookie dovrà contenere la sequenza nel suo nome e possiamo aggiungere un cookie aggiuntivo che contiene il numero di blocchi.

  • Il metodo read() eseguirà queste operazioni al contrario. Innanzitutto, riassembla ogni chunk dai cookie nella richiesta utilizzando il valore del cookie che contiene il numero di blocchi e quindi, facoltativamente, decrittografare i dati se lo abbiamo crittografato.

  • Il metodo destroy() dovrebbe cancellare il contenuto di ogni cookie che contiene un blocco.

  • Quindi sceglieremo un nome per il driver di sessione, come ad esempio cookie-extended , e, nel metodo boot() un service provider, lo registreremo come driver disponibile usando:

    Session::extend('cookie-extended', ...);
    

    Dovremo istruire l'applicazione, in config / session.php o in .env , per utilizzare il nuovo driver per le sessioni utente.

Se decidi di seguire questo percorso, assicurati di testare l'implementazione in ogni browser che intendi supportare, poiché i diversi browser impongono i propri limiti sulla dimensione e sulla quantità dei cookie. Anche se abbiamo aumentato la quantità di dati di sessione che possiamo memorizzare come cookie, siamo ancora limitati al numero massimo di cookie che un browser accetterà per dominio.

Come nota finale, l'archiviazione delle sessioni nel database potrebbe non influire sulle prestazioni quanto si pensa. Potrebbe valere la pena misurare il carico effettivo creato da questa semplice soluzione prima di investire molte ore per ottimizzare una preoccupazione che potrebbe non essere un problema reale.