我有一个使用Mojarra 2.2.9的JSF应用程序
并在WebSphere 8.5.5.4上部署在集群环境中
并且javax.faces.STATE_SAVING_METHOD
设置为client
。
即使我的所有应用程序bean都是请求作用域,但有时当用户会话有效且用户在页面上执行发布请求时,他会获得ViewExpiredException
。可能导致此问题的原因以及如何解决?
将javax.faces.STATE_SAVING_METHOD
改为server
会解决吗?如果是这样,这对内存的影响是什么?
此外,这是否与群集环境有关,可能在Websphere上有一些缺少配置来解决问题?
答案 0 :(得分:10)
如果客户端状态由一个服务器加密并由其他服务器解密,并且服务器不使用相同的AES密钥,则会发生这种情况。通常,您还应该在服务器日志中看到以下警告:
错误:MAC未验证
您需要确保在jsf/ClientSideStateKey
中使用固定的AES密钥设置web.xml
,否则每个服务器将在启动/重启期间(重新)生成自己的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>
您可以使用此代码段生成Base64格式的随机AES256(32位)密钥。
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: Illegal key size or default parameters?错误,请按照链接中的说明安装加密扩展,否则生成随机的AES128(16位)密钥。
获得密钥后,请确保不要发布/开源密钥。
此外,您还需要确保已将<distributable />
标记添加到web.xml
,以便JSF执行更具侵略性的会话变脏,并且HTTP会话(包括视图范围的bean本身!)在服务器之间正确同步。
ViewExpiredException
客户端状态保存的另一个可能原因是您在com.sun.faces.clientStateTimeout
中设置了特定于Mojarra的上下文参数web.xml
,它表示传入客户端之前的时间(以秒为单位)边态被认为已过期。然而,这种情况不太可能,因为上下文参数有一个相当自我解释的名称,你可以通过浏览web.xml
来发现它。
答案 1 :(得分:1)
如balusc
所述,您必须在web.xml中包含distributable标记