FullAjaxExceptionHandler does not show session expired error page on ajax button
Asked Answered
D

2

3

I have implemented Omnifaces FullAjaxExceptionHandler but the problem is It is not working with ajax requests. After session expires when I click to non-ajax button, It works well. It redirects user to custom error page. But if the button uses ajax, It doesn't do anything. Page just stucks.

Edit: I have changed ActionListener to Action and still same.

Edit2: It gives no error. Neither Apache Tomcat output nor Apache Tomcat Log.

enter image description here

here is my spring security;

<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>
Disharmony answered 25/6, 2013 at 11:44 Comment(5)
What's the contents of the ajax response?Myiasis
<p:menuitem value="open a new tab" action="#{myController.openNewTab()}" update=":contentPanel"/> I have a menuitem and when user clicks this menuitem, a tab in tabview will be rendered. By the way everytab includes different pages. Its like Google chrome. User has some bookmarks and if he clicks some bookmark, App will open it's page in a new tab.Disharmony
What's the contents of the ajax response? Press F12 in Chrome and check Network section to see it.Myiasis
@Myiasis I added as picture.Disharmony
So.. The ajax response is a 302 redirect? Do you have a homegrown login filter which is performing a response.sendRedirect() when the user is not logged-in or so?Myiasis
M
5

You're sending a synchronous redirect as a response to the ajax request (a HTTP 302 response using e.g. response.sendRedirect()). This is not right. The JavaScript ajax engine treats the 302 response as a new destination to re-send the ajax request to. However, that in turn returns a plain vanilla HTML page instead of a XML document with instructions which parts of the page to update. This is confusing and thus the redirected response is altogether ignored. That explains precisely the symptoms you're facing.

The very same problem is also asked and answered in the following closely related questions:

Basically, you need to instruct Spring Security in some way to perform the following conditional check:

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);
}

I'm however no Spring user and I'm not interested to use it, and am therefore not able to give a more detailed answer how to perform this check in Spring Security. I can however tell that Apache Shiro has exactly the same problem which is explained and solved in this blog article: Make Shiro JSF Ajax Aware.

Myiasis answered 25/6, 2013 at 12:36 Comment(5)
What you mean by loginURL? when i set it "/login.xhtml" the application tries to open localhost:8080/login.xhtml and gives not found error. When i set "/myApp/login.xhtml" it says "this page has too many redirect" error. Do you have any idea what is going on?Disharmony
It should be request.getContextPath() + "/login.xhtml". As to the "too many redirects" error, this means that it's redirecting in an infinite loop. Apparently you're also redirecting to login.xhtml when login.xhtml itself is been requested. You should then not redirect to login.xhtml, but continue the request by chain.doFilter(request, response). This answer comes close with what you probably need: stackoverflow.com/a/14582031Myiasis
problem is when I start the application, request.getRequestURI() comes with "/myApp/" string not with "/myApp/login.xhtml". A little confusingDisharmony
It seems that you're just adding a servlet filter instead of reconfiguring Spring Security. You basically need to change the Spring Security configuration/logic. This is unfortunately not just a matter of adding a servlet filter. I recommend to re-ask the question in the following context: "How do I change the way how Spring Security redirects the request to the login page? I need to return a XML response to an ajax request instead of a 302 response.".Myiasis
I solved the problem but still I don't what is going on behind :D anyway it works now. I changed some lines from stackoverflow.com/a/14582031 ; boolean loginRequest = (request1.getRequestURI().equals(request1.getContextPath() + "/")) || (request1.getRequestURI().equals(loginURL));Disharmony
C
1

In file 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>

The custom redirectStrategy (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);

        }

   }

work for me.

Cleveland answered 12/2, 2014 at 18:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.