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

S.C*_*.C. 8 javascript java session jquery jsp

以前,servlet使用response.sendRedirect("pages/my_page.jsp?foo=bar");没有问题.可以在重定向到的后续页面中检索会话属性.

目前,我正在改变发送请求的方式.最初,Javascript使用myForm.submit();,但我现在已将其更改为jQuery.ajax("my_page.jsp?foo=bar", {...});.然后,servlet在JSON响应中包含一个URL,而不是response.sendRedirect()success函数中,我window.location.replace(url);用来导航到新页面.但是,无法在后续页面中获取已保存的会话属性.

我通过插入<%= session.getId() %>JSP页面来比较会话ID .他们是一样的.这里的问题是重定向到的页面中的session.getAttribute("myAttribute_1")返回null.

我不确定这是否重要,但我实际上是在使用多个JSP页面执行此任务:

A.jsp --- (redirect) ---> B.jsp --- (redirect) ---> C.jsp
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如何获取保存的会话属性C.jsp


编辑

下面是我用来保存会话属性的代码片段.

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();
}
Run Code Online (Sandbox Code Playgroud)

以下是重定向的代码段.

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);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

结果

我已经恢复使用response.sendRedirect("pages/my_page.jsp?foo=bar")我的servlet了.

在客户端,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();
}
Run Code Online (Sandbox Code Playgroud)

每当我想提交表单时,click都会附加一个事件处理程序.它将调用sendFormData(myOriginalForm);而不是myOriginalForm.submit();我需要自定义要发送的数据.

只有应用这些简单的更改,一切都会再次起作用.

不过,我正在寻找关于这种奇怪行为的解释.

dig*_*ise 2

在服务器端

HTTP 请求是无状态的,会话通过不同的方式置于 HTTP 之上,例如

  • URL重写(例如服务器启动新会话并将其ID返回给客户端,然后客户端将会话ID附加到所有后续请求http://host:port/path;session_id=12345
  • cookie(例如,在会话创建时,服务器使用编码会话 ID 的 cookie 进行响应,并且在服务器端,您希望 cookie 将每个请求与现有会话相关联)。

客户端有责任确保它们以服务器期望的方式参与会话。当使用 Java Servlet API 实现服务器时,它是jsessionid cookie 或附加到 URL 的同名查询参数,用于标识会话 id。

如果客户端不支持 cookie,则使用 Java Servlet API 您将必须重定向到由HttpServletResponse.encodeRedirectURL(String url).

为了从 servlet 进行重定向,请使用HttpServletResponse.sendRedirect(String url);.

使用 HTTP 重定向标准从服务器进行响应将简化您的设计。Jquery确实实现了这些标准,因此将遵循来自服务器的HTTP 301302响应,如此处所示,因此客户端不需要重定向逻辑。


在客户端

您的客户端是jquery,当后续请求向同一域发出时,它的 ajax 实现将尊重并重播为任何给定域设置的 cookie。

如果您要重定向到其他域,为了使jquery能够与CORS会话配合使用,请xhrFields在您的请求中添加:

$.ajax({
    url: a_cross_domain_url,
    xhrFields: {
      withCredentials: true
    }
});
Run Code Online (Sandbox Code Playgroud)

根据这个答案