简体   繁体   中英

Session attribute is lost after invoking a client-side redirect

Previously, the servlet uses response.sendRedirect("pages/my_page.jsp?foo=bar"); without problem. Session attributes can be retrieved in the subsequent pages being redirected to.

Currently, I am changing the way to send requests. Originally, the Javascript uses myForm.submit(); , but I have now changed it to jQuery.ajax("my_page.jsp?foo=bar", {...}); . Then, the servlet includes a URL in the JSON response instead of response.sendRedirect() , and in the success function, I use window.location.replace(url); to navigate to the new page. However, the saved session attributes cannot be fetched in subsequent pages.

I have compared the session IDs by inserting <%= session.getId() %> in my JSP pages. They are the same. The issue here is session.getAttribute("myAttribute_1") returns null in the page redirected to.

I am not sure if this matters, but I am in fact doing this task with more than 1 JSP pages:

A.jsp --- (redirect) ---> B.jsp --- (redirect) ---> C.jsp

In this case, how can I get the saved session attributes in C.jsp ?


Edit

Below is the code snippet I use to save session attribute.

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    HttpSession session = request.getSession(true);

    response.setContentType("application/json");

    CustomObject customObject = new CustomObject();
    // ...
    session.setAttribute("myAttribute_1", customObject);

    PrintWriter writer = response.getWriter();
    JsonObject json = new JsonObject();
    Gson gson = new GsonBuilder().setPrettyPrinting().create();

    json.addProperty("url", "next_page.jsp?foo=bar");
    writer.println(gson.toJson(json));
    writer.close();
}

Below is the code snippet for redirecting.

function redirectHandler(data, currentUrl) {
    if (data && data.hasOwnProperty('url')) {
        var redirectUrl = data.url;
        jQuery.get(redirectUrl).done(function(response) {
            redirectHandler(response, redirectUrl);
        });
    } else {
        window.location.replace(currentUrl);
    }
}

function sendFormData(method, url, form) {
    jQuery.ajax(url, {
        'method': method,
        'data': parseData(jQuery(form).serializeArray()),
        'success': function(data) {
            redirectHandler(data, window.location.href);
        }
    });
}

Result

I have reverted back to using response.sendRedirect("pages/my_page.jsp?foo=bar") in my servlet.

On the client side, jQuery.ajax() is removed and the function sendFormData() is updated as follows.

function sendFormData(form) {
    var data = parseData(jQuery(form).serializeArray());
    var f = document.createElement('form');

    for (var key in data) {
        jQuery('<input>').attr({
            'type': 'hidden',
            'name': key,
            'value': data[key]
        }).appendTo(f);
    }

    f.setAttribute('method', form.getAttribute('method'));
    f.setAttribute('action', form.getAttribute('action'));
    f.submit();
}

Whenever I want to submit a form, a click event handler is attached. It will call sendFormData(myOriginalForm); rather than myOriginalForm.submit(); as I need to customize the data to be sent.

Only by applying these simple changes, everything works again.

Still, I am looking for an explanation on this weird behavior.

Have you tried different forms of Javascript redirects?

Recommended approach is:

window.location.href=currentUrl;

According to this article , using window.location.replace will replace the current session.

On the server side

HTTP requests are stateless and the sessions are laid on top of HTTP by different means like

  • URL rewriting (eg server starts new session and returns its ID to the client, then client appends session id to all subsequent requests http://host:port/path;session_id=12345 )
  • cookies (eg upon session creation server responds with a cookie encoding session ID, and on the server side you expect that cookie to correlate each request with existing session).

It is the client's responsibility to ensure that they participate in the session by the means expected by the server. When the server is implemented using Java Servlet API it is either jsessionid cookie or the query parameter with the same name appended to the URL, which identifies the session id.

If the client does not support cookies, using Java Servlet API you will have to redirect to a URL created by HttpServletResponse.encodeRedirectURL(String url) .

In order to redirect from a servlet use HttpServletResponse.sendRedirect(String url); .

Responding form the server with standard for HTTP redirects will simplify your design. Jquery does implement these standards and therfore will honour HTTP 301 and 302 responses from the server as ilustrated here so no redirect logic on the client side should be needed.


On the client side

Your client is jquery and its ajax implementation will respect and replay the cookies set for any given domain, when subsequent request will be made to the same domain.

If you are redirecting to a different domain, for jquery to work with CORS sessions, please add xhrFields to your request:

$.ajax({
    url: a_cross_domain_url,
    xhrFields: {
      withCredentials: true
    }
});

as per this answer

I had the same issue and tore my hair out looking for the best solution . Try putting sessionCookiePath="/" attribute into your context.xml root node:

<Context ... sessionCookiePath="/" > ... </Context>

This will set the path of your session cookie to the root of your app so that it will be passed on redirect. This simple fix worked for me.

Many people will suggest URL encoding or storing the session ID in another cookie, but based on my understanding this is the best solution if it works for you. (Session cookies are considered strictly necessary , so using them as intended is probably best practice.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM