Изглежда, че възражението ви да оставите сесията да остане отворена, докато браузърът е отворен, е въпрос на автоматизирани атаки. За съжаление опресняването на токена при всяко зареждане на страница възпира само най-аматьорските нападатели.
Първо, предполагам, че говорим за атаки, конкретно насочени към вашия сайт. (Ако говорим за ботове, които просто обикалят наоколо и изпращат различни формуляри, това не само няма да ги спре, но има много по-добри и по-лесни начини да го направите.) Ако случаят е такъв, и аз се насочвам към моя сайт, ето какво би направил моят бот:
- Зареждане на страница с формуляр.
- Прочетете токена на страницата с формуляр.
- Изпратете автоматизирана заявка с това означение.
- Отидете на стъпка 1.
(Или, ако проучих достатъчно вашата система, щях да разбера, че ако включа заглавката „this is AJAX“ във всяка заявка, бих могъл да запазя един токен завинаги. Или щях да разбера, че токенът е моят ID на сесията и изпратете моя собствен PHPSESSID
бисквитка.)
Този метод за промяна на токена при всяко зареждане на страница няма да направи абсолютно нищо, за да спре някой, който действително иска да те атакувам толкова лошо. Следователно, тъй като токенът няма ефект върху автоматизацията, фокусирайте се върху ефектите му върху CSRF.
От гледна точка на блокирането на CSRF, създаването на един токен и поддържането му, докато потребителят затвори браузъра, изглежда постига всички цели. Простите CSRF атаки са победени и потребителят може да отваря множество раздели.
TL;DR:Опресняването на токена веднъж при всяка заявка не повишава сигурността. Заложете на използваемостта и правете по едно означение на сесия.
Въпреки това! Ако сте изключително загрижени за дублиращи се изпращания на формуляри, случайни или по друг начин, този проблем може лесно да бъде решен. Отговорът е прост:използвайте два токена за две различни задачи.
Първият токен ще остане същият, докато сесията на браузъра приключи. Този токен съществува за предотвратяване на CSRF атаки. Всяко изпращане от този потребител с това означение ще бъде прието.
Вторият токен ще бъде уникално генериран за всеки зареден формуляр и ще бъде съхранен в списък в данните за сесията на потребителя на токени за отворен формуляр. Този токен е уникален и се анулира, след като бъде използван. Изпращанията от този потребител с това означение ще бъдат приети веднъж и само веднъж.
По този начин, ако отворя раздел към формуляр A и раздел към формуляр B, всеки от тях има моя личен anti-CSRF токен (за CSRF се грижи) и моя еднократен токен за формуляр (повторното изпращане на формуляр е обгрижено). И двата проблема са разрешени без никакво лошо въздействие върху потребителското изживяване.
Разбира се, може да решите, че това е твърде много за прилагане за такава проста функция. Мисля, че така или иначе. Независимо от това, съществува солидно решение, ако го искате.