Ответ 1
Это указано/ожидаемое поведение при сохранении состояния клиентской стороны. Состояние представления JSF не сохраняется в сеансе, но полностью в скрытом поле ввода в форме HTML на стороне клиента. Только при использовании сохранения состояния на стороне сервера состояние представления JSF будет недействительным, если оно не существует в пользовательском сеансе HTTP.
Я не вижу любым способом в MyFaces, чтобы аннулировать сохраненное состояние на стороне клиента, если оно повторно связано с "неправильным" сеансом во время постбэк. Параметр контекста org.apache.myfaces.CLIENT_VIEW_STATE_TIMEOUT
близок. Вы можете установить его в то же время, что и время ожидания сеанса.
Сценарий атаки CSRF - это ИМО, немного преувеличенный. Во-первых, злоумышленник должен иметь возможность получить руку от состояния клиентской стороны. Самый простой способ - это отверстие XSS. Только JSF повсеместно предотвращает атаку XSS (если вы осторожны с escape="false"
). Самый сложный способ - иметь руку всего HTML-вывода. Это можно сделать с помощью атаки "человек в середине". Только это также дает злоумышленнику весь сеансовый файл cookie, поэтому весь сценарий атаки CSRF в этом случае "излишне усложняется" для злоумышленника, так как злоумышленник может просто захватить сеанс. Лучшая защита от этого - просто использование HTTPS вместо HTTP.
Даже тогда, если злоумышленник каким-то образом получил представление о состоянии стороны на стороне клиента, злоумышленник не может делать с ним много опасных вещей без дешифрования, неэриализации и манипулирования им. MyFaces шифрует его по умолчанию в течение длительного времени (уже с раннего 2.0.x). Злоумышленник не может расшифровать его, не имея правильного ключа и, следовательно, также не манипулировать им. Это шифрование состояния просмотра на стороне клиента, кстати, становится обязательной частью спецификации JSF 2.2 (поэтому Mojarra также делает это). Этот ключ получает по умолчанию reset при перезапуске сервера приложений (и, следовательно, все состояния клиентской стороны будут аннулированы). Вы можете, если необходимо, указать фиксированный ключ, указав ниже запись среды в web.xml
:
<env-entry>
<env-entry-name>jsf.ClientSideSecretKey</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>[AES key in Base64 format]</env-entry-value>
</env-entry>
Вы можете использовать эту страницу для создания случайного ключа AES в формате Base64.
Даже тогда, если злоумышленнику каким-то образом удастся расшифровать состояние представления и получить другого пользователя для его фактического представления (например, через отверстие XSS или фишинговый сайт), тогда лучше всего включить токен CSRF на основе сеанса HTTP в страницу JSF. Но также это небезопасно, если у webapp по-прежнему есть дыра XSS-атаки, или передается через HTTP вместо HTTPS.