2

我有一个在 glassfish 3.1 上运行的 JSF 2.0 Web 应用程序,它在 IE、FF、Safari 和 Chrome 上运行良好。

当我在另一个网站的 iframe 中添加我的网站的 url 时,单击 iframe 中的任何按钮后,我得到 ViewExpiredException - 这仅在 Safari 上发生,在 IE、FF、Chrome 中运行良好。

<iframe style="width: 100%; height: 800px" src="url_of_my_website" frameBorder="0"></iframe>

以下是我的观察

  1. 在 glassfish 3.0.1 上部署了相同的应用程序,问题没有发生
  2. 如果我在没有框架的情况下打开我的网站,无论浏览器如何,它都可以正常工作
  3. 使用 JSF1.2 和 RF 3.3.3 开发了相同的应用程序,问题没有发生

根据我的理解,当在会话过期的页面上执行任何操作时,我们会得到 ViewExpiredException。但在这种特殊情况下,它发生在网站加载加载之后。

我不确定是什么原因造成的。是 Safari/JSF 2.0/GF 3.1/IFRAME?

更新: 我发现了一个有趣的问题。在我的主页上,我有 ah:commandLink 将我重定向到新页面。另外,我有一个 href 链接可以重定向到其他页面。当我单击 commandLink 时,我得到 ViewExpiredException 但是当我单击 href 链接时,我没有得到任何异常并且页面被重定向并且我可以在会话 cookie 建立时继续进行进一步的操作。

4

2 回答 2

3

这确实是一个已知问题。Safari 不允许跨域 cookie。由 iframe 提供的任何 cookie 将被此浏览器忽略。HTTP 会话由 cookie 支持。所以它也不会被维护。因此,当您在 iframe 中提交 JSF 表单时,Safari 不会发回会话 cookie,服务器端将隐式创建一个新会话,因此在初始会话中设置的视图完全丢失。因此ViewExpiredException.

理论上,这可以通过在 JSF 生成的 HTML元素JSESSIONID的 URL 中包含片段来解决。例如action<form>

<form action="/context/page.xhtml;JSESSIONID=1234567890ABCDEF">

但是,JSF 已经这样做了。它在幕后使用HttpServletResponse#encodeURL()。它在 JSF 2 上对你不起作用,而它显然在 JSF 1.2 上起作用,这对我来说是个谜。但你现在至少有一些事情要集中精力。是否HttpServletResponse#encodeURL()返回了正确编码的 URL JSESSIONID?生成的 HTML 是否<form>包含JSESSIONID? 等等 使用 Mojarra 时,FormRenderer#getActionStr()一边调试一边从方法开始。

无论如何,另一种解决方案是为此使用 JavaScript。在加载要在 iframe 中显示的 JSF 页面期间执行以下操作。以下脚本启动示例应嵌入 JSF 页面中,以便#{}对其进行评估。

window.onload = function() {
    if (top != self) { // If true, then page is been requested inside an iframe.
        var jsessionid = '#{session.id}';
        var forms = document.forms;

        for (var i = 0; i < forms.length; i++) {
            forms[i].action += ';JSESSIONID=' + jsessionid;
        }
    }
}

不应损害 Safari 以外的浏览器。

于 2011-08-12T16:23:08.770 回答
0

我在 IE 和 Safari 上遇到了同样的问题。这是因为这些浏览器默认不允许第三方 cookie。因此会话 id 无法通过 cookie 传递。

要在 IE 中修复它,只需添加值为 CP="This site doesn't have a p3p policy." 的响应头 P3P 即可:

ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();
extContext.addResponseHeader("P3P", "CP=\"This site does not have a p3p policy.\"");

在 Safari 中修复它就足以在 url 中传输会话 id 而不是在 cookie 中。这称为 url 重写。对于支持 Servlet 3.0 的应用程序服务器,可以使用 web.xml 来完成:

<session-config>
    <tracking-mode>URL</tracking-mode> 
</session-config>
于 2016-05-24T12:41:49.153 回答