简体   繁体   English

调用客户端重定向后会话属性丢失

[英]Session attribute is lost after invoking a client-side redirect

Previously, the servlet uses response.sendRedirect("pages/my_page.jsp?foo=bar");以前,servlet 使用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();最初,Javascript 使用myForm.submit(); , but I have now changed it to jQuery.ajax("my_page.jsp?foo=bar", {...}); ,但我现在已将其更改为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);然后,servlet 在 JSON 响应中包含一个 URL 而不是response.sendRedirect() ,并且在success函数中,我使用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.我通过在 JSP 页面中插入<%= session.getId() %>比较了会话 ID。 They are the same.他们是一样的。 The issue here is session.getAttribute("myAttribute_1") returns null in the page redirected to.这里的问题是session.getAttribute("myAttribute_1")在重定向到的页面中返回null

I am not sure if this matters, but I am in fact doing this task with more than 1 JSP pages:我不确定这是否重要,但实际上我正在使用 1 个以上的 JSP 页面执行此任务:

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

In this case, how can I get the saved session attributes in C.jsp ?在这种情况下,如何在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.我已经恢复使用response.sendRedirect("pages/my_page.jsp?foo=bar")在我的 servlet 中。

On the client side, jQuery.ajax() is removed and the function sendFormData() is updated as follows.在客户端, jQuery.ajax()被删除, sendFormData()函数更新如下。

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.每当我想提交表单时,都会附加一个click事件处理程序。 It will call sendFormData(myOriginalForm);它将调用sendFormData(myOriginalForm); rather than myOriginalForm.submit();而不是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? 您是否尝试过其他形式的Javascript重定向?

Recommended approach is: 推荐的方法是:

window.location.href=currentUrl;

According to this article , using window.location.replace will replace the current session. 根据本文的介绍 ,使用window.location.replace将替换当前会话。

On the server side 在服务器端

HTTP requests are stateless and the sessions are laid on top of HTTP by different means like HTTP请求是无状态的,会话通过不同的方式位于HTTP之上

  • 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 ) URL重写 (例如,服务器开始新的会话并将其ID返回给客户端,然后客户端将会话ID附加到所有后续请求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). cookie (例如,在创建会话时,服务器以cookie编码的会话ID进行响应,并且在服务器端,您希望该cookie将每个请求与现有会话相关联)。

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. 使用Java Servlet API实现服务器时,它是jsessionid cookie或URL后面带有相同名称的查询参数,用于标识会话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) . 如果客户端不支持cookie,则必须使用Java Servlet API重定向到HttpServletResponse.encodeRedirectURL(String url)创建的HttpServletResponse.encodeRedirectURL(String url)

In order to redirect from a servlet use HttpServletResponse.sendRedirect(String url); 为了从servlet重定向,请使用HttpServletResponse.sendRedirect(String url); .

Responding form the server with standard for HTTP redirects will simplify your design. 使用标准的HTTP重定向响应服务器将简化您的设计。 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. jQuery确实实现了这些标准,因此将遵循此处说明的来自服务器的HTTP 301302响应,因此客户端上不需要重定向逻辑。


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. 您的客户端是jquery ,当后续对同一域发出请求时,其ajax实现将尊重并重播为任何给定域设置的cookie。

If you are redirecting to a different domain, for jquery to work with CORS sessions, please add xhrFields to your request: 如果您要重定向到其他域,则要让jquery使用CORS会话,请在请求中添加xhrFields

$.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:尝试将sessionCookiePath="/"属性放入您的 context.xml 根节点:

<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.这会将会话 cookie 的路径设置为应用程序的根目录,以便在重定向时传递。 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.许多人会建议 URL 编码或将会话 ID 存储在另一个 cookie 中,但根据我的理解,如果它适合您,这是最好的解决方案。 (Session cookies are considered strictly necessary , so using them as intended is probably best practice.) (会话 cookie 被认为是绝对必要的,因此按预期使用它们可能是最佳实践。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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