【问题标题】:FullAjaxExceptionHandler does not show session expired error page on ajax buttonFullAjaxExceptionHandler 不在 ajax 按钮上显示会话过期错误页面
【发布时间】:2013-06-22 04:42:30
【问题描述】:

我已经实现了 Omnifaces FullAjaxExceptionHandler 但问题是它不适用于 ajax 请求。会话到期后,当我单击非 ajax 按钮时,它运行良好。它将用户重定向到自定义错误页面。但是如果按钮使用 ajax,它什么也做不了。页面卡住了。

编辑:我已将 ActionListener 更改为 Action 并且仍然相同。

Edit2:它没有给出错误。 Apache Tomcat 输出和 Apache Tomcat 日志都没有。

这是我的春季安全;

<http auto-config='true' use-expressions="true">
    <intercept-url pattern="/login" access="permitAll"/>
    <intercept-url pattern="/ajaxErrorPage" access="permitAll"/>
    <intercept-url pattern="/pages/*" access="hasRole('admin')" />
    <intercept-url pattern="/j_spring_security_check" access="permitAll"/>        
    <logout logout-success-url="/login.xhtml" />
    <form-login login-page="/login.xhtml"
                login-processing-url="/j_spring_security_check"                                                       
                default-target-url="/pages/index.xhtml"
                always-use-default-target="true"                                                        
                authentication-failure-url="/login.xhtml"/>
</http>

【问题讨论】:

  • ajax响应的内容是什么?
  • 我有一个菜单项,当用户点击这个菜单项时,将呈现 tabview 中的选项卡。顺便说一句,每个选项卡都包含不同的页面。它就像谷歌浏览器。用户有一些书签,如果他点击一些书签,应用程序将在新标签页中打开它的页面。
  • ajax 响应的内容是什么?在 Chrome 中按 F12 并检查 Network 部分以查看它。
  • @BalusC 我添加为图片。
  • 所以.. ajax 响应是 302 重定向?您是否有一个本地登录过滤器在用户未登录时执行response.sendRedirect()

标签: jsf jsf-2 omnifaces


【解决方案1】:

在 spring-security 文件中 (en el archivo de Spring Security)

<beans:bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>

<!-- redirection strategy -->
<beans:bean id="jsfRedirectStrategy" class="com.mycompany.JsfRedirectStrategy">
    <beans:property name="invalidSessionUrl" value="/login.xhtml" />
</beans:bean>

<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
    <beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />
    <beans:property name="invalidSessionStrategy" ref="jsfRedirectStrategy" />
</beans:bean>

<http auto-config='true' use-expressions="true">
    <intercept-url pattern="/login" access="permitAll"/>
    <intercept-url pattern="/ajaxErrorPage" access="permitAll"/>
    <intercept-url pattern="/pages/*" access="hasRole('admin')" />
    <intercept-url pattern="/j_spring_security_check" access="permitAll"/>        
    <logout logout-success-url="/login.xhtml" />
    <form-login login-page="/login.xhtml"
            login-processing-url="/j_spring_security_check"                                                       
            default-target-url="/pages/index.xhtml"
            always-use-default-target="true"                                                        
            authentication-failure-url="/login.xhtml"/>

     <!-- custom filter -->
    <custom-filter ref="sessionManagementFilter"  before="SESSION_MANAGEMENT_FILTER" />

</http>

自定义重定向策略 (La estrategia de redirección personalizada)

public class JsfRedirectStrategy implements InvalidSessionStrategy
{

    private static final String FACES_REQUEST = "Faces-Request";

    private String invalidSessionUrl;

    public void setInvalidSessionUrl(String invalidSessionUrl) {
        this.invalidSessionUrl = invalidSessionUrl;
    }

    public String getInvalidSessionUrl() {
       return invalidSessionUrl;
    }



    @Override
    public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {



        String contextPath = request.getContextPath();
        String urlFinal = contextPath+invalidSessionUrl;




        if ("partial/ajax".equals(request.getHeader(FACES_REQUEST))) {
            // with ajax
            response.setContentType("text/xml");
            response.getWriter()
                .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
                .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", urlFinal);
        } else {

            // not ajax
            request.getSession(true);
            response.sendRedirect(urlFinal);

        }

   }

为我工作。

【讨论】:

    【解决方案2】:

    您正在发送同步重定向作为对 ajax 请求的响应(使用例如 response.sendRedirect() 的 HTTP 302 响应)。这个不对。 JavaScript ajax 引擎将 302 响应视为重新发送 ajax 请求的新目的地。但是,这反过来会返回一个普通的 HTML 页面,而不是一个 XML 文档,其中包含要更新页面的哪些部分的说明。这是令人困惑的,因此重定向的响应完全被忽略了。这准确地解释了你所面临的症状。

    在以下密切相关的问题中也提出并回答了同样的问题:

    基本上,您需要以某种方式指示 Spring Security 执行以下条件检查:

    if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
        // JSF ajax request. Return special XML response which instructs JavaScript that it should in turn perform a redirect.
        response.setContentType("text/xml");
        response.getWriter()
            .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
            .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", loginURL);
    } else {
        // Normal request. Perform redirect as usual.
        response.sendRedirect(loginURL);
    }
    

    然而,我不是 Spring 用户,我对使用它不感兴趣,因此无法给出更详细的答案,如何在 Spring Security 中执行此检查。然而,我可以说 Apache Shiro 有完全相同的问题,在这篇博客文章中解释和解决了这个问题:Make Shiro JSF Ajax Aware

    【讨论】:

    • loginURL 是什么意思?当我将其设置为“/login.xhtml”时,应用程序尝试打开localhost:8080/login.xhtml 并给出未找到错误。当我设置“/myApp/login.xhtml”时,它显示“此页面有太多重定向”错误。你知道发生了什么吗?
    • 应该是request.getContextPath() + "/login.xhtml"。至于“重定向太多”错误,这意味着它在无限循环中重定向。显然,当 login.xhtml 本身被请求时,您也会重定向到 login.xhtml。然后,您不应重定向到 login.xhtml,而是通过chain.doFilter(request, response) 继续请求。这个答案与您可能需要的很接近:stackoverflow.com/a/14582031
    • 问题是当我启动应用程序时,request.getRequestURI() 带有“/myApp/”字符串而不是“/myApp/login.xhtml”。有点混乱
    • 看来您只是添加了一个 servlet 过滤器,而不是重新配置 Spring Security。您基本上需要更改 Spring Security 配置/逻辑。不幸的是,这不仅仅是添加 servlet 过滤器的问题。我建议在以下上下文中重新提出问题:“如何更改 Spring Security 将请求重定向到登录页面的方式?我需要将 XML 响应返回到 ajax 请求而不是 302 响应。”。
    • 我解决了这个问题,但我仍然不知道背后发生了什么:D 无论如何它现在可以工作了。我从 stackoverflow.com/a/14582031 更改了一些行; boolean loginRequest = (request1.getRequestURI().equals(request1.getContextPath() + "/")) || (request1.getRequestURI().equals(loginURL));
    猜你喜欢
    • 2013-04-08
    • 2012-01-15
    • 2013-09-06
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多