我有一个使用 Mojarra 2.2.9 的 JSF 应用程序
并部署在集群环境中的 WebSphere 8.5.5.4 上
和 javax.faces.STATE_SAVING_METHOD
设置为 client
.
即使我的所有应用程序 bean 都是请求范围的,有时当用户 session 有效并且用户在页面上执行发布请求时,他会收到 ViewExpiredException
.什么可能导致此问题,我该如何解决?
会改javax.faces.STATE_SAVING_METHOD
至 server
解决这个问题?如果是这样,这样做对内存有什么影响?
另外,这是否与集群环境有关,也许 Websphere 上缺少一些可以解决问题的配置?
最佳答案
如果客户端状态由一台服务器加密并由另一台服务器解密,并且服务器不为此使用相同的 AES key ,则会发生这种情况。通常,您还应该在服务器日志中看到以下警告:
ERROR: MAC did not verify
您需要确保您已设置
jsf/ClientSideSecretKey
在 web.xml
使用固定的 AES key ,否则每个服务器将在启动/重启期间(重新)生成自己的 AES key (在加密 View 状态期间使用)。<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 位) key 。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 位) key 。获得 key 后,请务必确保不要发布/开源您的 key 。
此外,您还需要确保已添加
<distributable />
标记到 web.xml
因此 JSF 将执行更激进的 session 脏化,并且 HTTP session (包括 View 范围的 bean 本身!)在服务器之间正确同步。另一个可能的原因
ViewExpiredException
客户端状态保存是您已经设置了 Mojarra 特定的上下文参数 com.sun.faces.clientStateTimeout
在 web.xml
它表示传入客户端状态被视为过期之前的时间(以秒为单位)。然而,这里不太可能出现这种情况,因为该上下文参数有一个相当不言自明的名称,您只需扫一眼 web.xml
就会发现该名称。 .也可以看看:
关于jsf - 当状态保存方法设置为客户端且用户 session 有效时,在集群环境中获取ViewExpiredException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19521087/