Получение ViewExpiredException в кластерной среде, когда для метода сохранения состояния задано значение клиента, а сеанс пользователя действителен
У меня есть приложение JSF, которое использует Mojarra 2.2.9 и развернуто в WebSphere 8.5.5.4 в кластерной среде и javax.faces.STATE_SAVING_METHOD
установлен в client
,
Несмотря на то, что все мои компоненты приложения находятся в области запросов, иногда, когда пользовательский сеанс действителен, и пользователь выполняет пост-запрос на странице, которую он получает ViewExpiredException
, Что может быть причиной этой проблемы и как я могу ее решить? Будет изменение javax.faces.STATE_SAVING_METHOD
в server
реши это? Если да, то как это влияет на память?
Кроме того, это как-то связано с окружением кластера, и, возможно, в Websphere отсутствует какая-то конфигурация, которая решит проблему?
2 ответа
Это произойдет, если состояние на стороне клиента зашифровано одним сервером и расшифровано другим сервером, и серверы не используют для этого один и тот же ключ AES. Как правило, вы также должны были видеть ниже предупреждение в журнале сервера:
ОШИБКА: MAC не проверен
Вы должны убедиться, что вы установили jsf/ClientSideStateKey
в web.xml
с фиксированным ключом AES, в противном случае каждый сервер будет (повторно) генерировать свой собственный ключ AES во время запуска / перезапуска (который используется во время состояния просмотра шифрования).
<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>
Вы можете использовать этот фрагмент для генерации случайного AES256 (32-битного) ключа в формате Base64.
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // Use 128 for 16bit key.
String key = Base64.getEncoder().encodeToString(keyGen.generateKey().getEncoded());
System.out.println(key); // Prints AES key in Base64 format.
Если вы получаете Java Security: Неверный размер ключа или параметры по умолчанию? ошибка, установите расширение криптографии, как указано в ссылке, или вместо этого сгенерируйте случайный ключ AES128 (16 бит).
Получив ключ, убедитесь, что вы не публикуете / не открываете ваш ключ.
Далее вы также должны убедиться, что вы добавили <distributable />
тег к web.xml
поэтому JSF будет выполнять более агрессивное загрязнение сеансов, а сеансы HTTP (включая сами компоненты bean-объекта view!) правильно синхронизируются между серверами.
Еще одна вероятная причина ViewExpiredException
с сохранением состояния на стороне клиента является то, что вы установили параметры контекста Mojarra com.sun.faces.clientStateTimeout
в web.xml
который представляет время в секундах до того, как состояние входящей клиентской стороны считается истекшим. Это, однако, маловероятно, так как этот контекстный параметр имеет довольно самоочевидное имя, которое вы бы заметили, просто взглянув на web.xml
,
Смотрите также:
Вы должны иметь распространяемый тег в вашем файле web.xml, как упомянуто balusc