Подделка запроса на межсайтовый запрос (CSRF) обычно предотвращается одним из следующих способов:
- Проверить референт - RESTful, но ненадежный
- добавить токен в форму и сохранить токен в сеансе сервера - не действительно RESTful
- загадочные одноразовые URI - не RESTful по той же причине, что и токены
- отправить пароль вручную для этого запроса (не кешированный пароль, используемый с HTTP-аутентификацией) - RESTful, но не удобно
Моя идея - использовать секрет пользователя, загадочный, но статический идентификатор формы и JavaScript для генерации токенов.
<form method="POST" action="/someresource" id="7099879082361234103">
<input type="hidden" name="token" value="generateToken(...)">
...
</form>
-
GET /usersecret/john_doe
, полученный JavaScript от пользователя, прошедшего проверку подлинности. - Ответ:
OK 89070135420357234586534346
Этот секрет концептуально статичен, но может меняться каждый день/час... для повышения безопасности. Это единственная конфиденциальная вещь. - Прочитайте криптовальный (но статический для всех пользователей!) идентификатор формы с JavaScript, обработайте его вместе с секретом пользователя:
generateToken(7099879082361234103, 89070135420357234586534346)
- Отправьте форму вместе с созданным токеном на сервер.
- Поскольку сервер знает секрет пользователя и идентификатор формы, можно запустить ту же функцию generateToken, что и клиент, перед отправкой и сравнением обоих результатов. Только когда оба значения равны, действие будет разрешено.
Что-то не так с этим подходом, несмотря на то, что он не работает без JavaScript?
Добавление: