在Safari中使用iframe时,Glassfish 3.1上的JSF 2.0 ViewExpiredException

在Safari中使用iframe时,Glassfish 3.1上的JSF 2.0 ViewExpiredException,iframe,safari,jsf-2,glassfish-3,viewexpiredexception,Iframe,Safari,Jsf 2,Glassfish 3,Viewexpiredexception,我有一个JSF2.0Web应用程序运行在GlassFish3.1上,在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">

我有一个JSF2.0Web应用程序运行在GlassFish3.1上,在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>

以下是我的观察结果

  • 在glassfish 3.0.1上部署了相同的应用程序,但问题没有发生
  • 如果我打开没有框架的网站,无论浏览器如何,它都可以正常工作
  • 使用JSF1.2和RF 3.3.3开发了相同的应用程序,但问题没有发生
  • 根据我的理解,当在会话已过期的页面上执行任何操作时,我们会得到ViewExpiredException。但在这种特殊情况下,它发生在网站加载之后

    我不确定是什么引起的。是Safari/JSF2.0/GF 3.1/IFRAME吗

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

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

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

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

    这不会对Safari以外的浏览器造成伤害。

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

    要在IE中修复它,只需添加值为CP=“此站点没有P3P策略”的响应头P3P即可:

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

    <session-config>
        <tracking-mode>URL</tracking-mode> 
    </session-config>
    
    
    统一资源定位地址
    
    感谢您的回复。我尝试了javascript,但它对我不起作用。我所有的页面都使用一个模板,所以我在那里添加了javascript。仅供参考,在我的筛选器的doFilter()方法中,我正在检查HttpServletRequest#isRequestSessionIdFromURL(),如果为真,则我将用户重定向到主页。如果解决方案javascript有效,这会是一个问题吗?根据您的更新:这是正常的。commandlink提交一个隐藏表单并有效地触发POST请求,因此要求在同一会话中触发该请求。普通链接触发GET请求,该请求不需要在同一会话中触发。只要在必要时创建一个新会话即可。如果您不需要提交额外的POST数据,那么您根本不需要commandlink。
    ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();
    extContext.addResponseHeader("P3P", "CP=\"This site does not have a p3p policy.\"");
    
    <session-config>
        <tracking-mode>URL</tracking-mode> 
    </session-config>