Det lyder som om, at din indsigelse mod at lade sessionen forblive åben, så længe browseren er åben, er et spørgsmål om automatiske angreb. Desværre afskrækker opdatering af tokenet ved hver sideindlæsning kun de mest amatørangribere.
For det første antager jeg, at vi taler om angreb, der er specifikt rettet mod dit websted. (Hvis vi taler om de bots, der bare strejfer rundt og indsender forskellige formularer, ville dette ikke kun stoppe dem, men der er langt bedre og nemmere måder at gøre det på.) Hvis det er tilfældet, og jeg målretter min websted, her er hvad min bot ville gøre:
- Indlæs formularsiden.
- Læs token på formularsiden.
- Send en automatisk anmodning med det token.
- Gå til trin 1.
(Eller, hvis jeg undersøgte dit system nok, ville jeg indse, at hvis jeg inkluderede "dette er AJAX"-headeren på hver anmodning, kunne jeg beholde et token for evigt. Eller jeg ville indse, at tokenet er mit sessions-id, og send mit eget PHPSESSID
cookie.)
Denne metode til at ændre tokenet ved hver sideindlæsning ville absolut intet gøre for at stoppe nogen, der faktisk ønskede at angribe dig så hårdt. Derfor, da tokenet ikke har nogen effekt på automatisering, skal du fokusere på dets virkninger på CSRF.
Ud fra perspektivet om at blokere CSRF ser det ud til at oprette et token og vedligeholde det, indtil brugeren lukker browseren, at nå alle mål. Simple CSRF-angreb bliver besejret, og brugeren er i stand til at åbne flere faner.
TL;DR:Opdatering af tokenet én gang på hver anmodning øger ikke sikkerheden. Gå efter brugervenlighed og lav et token pr. session.
Imidlertid! Hvis du er meget bekymret over duplikerede formularindsendelser, utilsigtet eller på anden måde, kan dette problem stadig nemt løses. Svaret er enkelt:Brug to tokens til to forskellige job.
Det første token forbliver det samme, indtil browsersessionen slutter. Dette token findes for at forhindre CSRF-angreb. Enhver indsendelse fra denne bruger med dette token vil blive accepteret.
Det andet token vil blive entydigt genereret for hver indlæst formular og vil blive gemt på en liste i brugerens sessionsdata for åbne formular-tokens. Dette token er unikt og er ugyldigt, når det er brugt. Indsendelser fra denne bruger med dette token vil blive accepteret én gang og kun én gang.
På denne måde, hvis jeg åbner en fane til formular A og en fane til formular B, har hver af dem mit personlige anti-CSRF-token (CSRF taget hånd om) og mit engangsformulartoken (formulargenindsendelse taget hånd om). Begge problemer er løst uden nogen negativ indvirkning på brugeroplevelsen.
Selvfølgelig kan du beslutte, at det er for meget at implementere for en så simpel funktion. Det tror jeg i hvert fald. Uanset hvad, findes der en solid løsning, hvis du ønsker det.