При перехоплених трафіку вам нічого не допоможе. там і логін і пароль засвятятся. І SSL не допоможе якщо man in the middle застосувати. Давайте тоді ще одноразові паролі використовувати. І пофіг що клієнту буде не зручно (ваш токен який на кожен реквест різний це «прощай юзабіліті», відкрили ваш сайт в двох табах, на обох різні маркери, який з них правильний?)
Генерувати новий токен на кожен запит може привести до помилок при відкритті сайту в декількох вкладках або при аякс-запитах (які викличуть генерацію нового токена).
Якщо зловмисник перехоплює трафік, CSRF нічим не допоможе, так як всі дані можна прочитати. Використовуйте HTTPS для захисту від перехоплення трафіку.
Токен досить мати один на сесію. При розбіжності токена треба показати повідомлення «Сталася помилка. Будь ласка, перевірте введені дані, і відправте форму ще раз ».
Природно, повідомлення треба показати разом з формою з заповненими даними, а не на порожній стрнаіце.
GET-форми, які не вносять змін до бази даних, на кшталт форми пошуку, не треба захищати.
Подивіться як це реалізовано в фрейворках. Наприклад Symfony, YII і т.п.
Зазвичай логіка така: в екшені контролера з формою перевіряємо - якщо POST (значить йде збереження форми), то перевіряємо токен. Якщо токен не збігається, то просто не зберігаємо дані, а відображаємо ту ж форму але з помилкою «Невірний токен».
І токени зазвичай використовуються в формах при збереженні даних. Для форми пошуку не бачу сенсу їх використовувати.
Сенсу для пошуку звичайно немає. Але додаток велике і форм багато, тому я зробив перевірку в BasicController, а там відрізнити POST пошуку від інших дій не така тривіальна задача. Крім того, навіть для «не пошук» редирект по F5 на 404 мені не здається вдалою ідеєю. Дивно що це у всіх гайдах по CSRF рекомендують.
> Просто не зберігаємо дані
Ну в принципі я майже так і зробив. У BasicController очищаю дані з POST, і показується порожня форма. Але це якось не дуже красиво. Думав, може є якесь _правільное_ рішення.