簡體   English   中英

調用客戶端重定向后會話屬性丟失

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

以前,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); 導航到新頁面。 但是,無法在后續頁面中獲取保存的會話屬性。

我通過在 JSP 頁面中插入<%= session.getId() %>比較了會話 ID。 他們是一樣的。 這里的問題是session.getAttribute("myAttribute_1")在重定向到的頁面中返回null

我不確定這是否重要,但實際上我正在使用 1 個以上的 JSP 頁面執行此任務:

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

在這種情況下,如何在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();
}

下面是重定向的代碼片段。

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

結果

我已經恢復使用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();
}

每當我想提交表單時,都會附加一個click事件處理程序。 它將調用sendFormData(myOriginalForm); 而不是myOriginalForm.submit(); 因為我需要自定義要發送的數據。

只有通過應用這些簡單的更改,一切才能恢復正常。

不過,我正在尋找對這種奇怪行為的解釋。

您是否嘗試過其他形式的Javascript重定向?

推薦的方法是:

window.location.href=currentUrl;

根據本文的介紹 ,使用window.location.replace將替換當前會話。

在服務器端

HTTP請求是無狀態的,會話通過不同的方式位於HTTP之上

  • URL重寫 (例如,服務器開始新的會話並將其ID返回給客戶端,然后客戶端將會話ID附加到所有后續請求http://host:port/path;session_id=12345
  • cookie (例如,在創建會話時,服務器以cookie編碼的會話ID進行響應,並且在服務器端,您希望該cookie將每個請求與現有會話相關聯)。

客戶有責任通過服務器期望的方式確保他們參與會話。 使用Java Servlet API實現服務器時,它是jsessionid cookie或URL后面帶有相同名稱的查詢參數,用於標識會話ID。

如果客戶端不支持cookie,則必須使用Java Servlet API重定向到HttpServletResponse.encodeRedirectURL(String url)創建的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
    }
});

按照這個答案

我遇到了同樣的問題,並撕毀了我的頭發以尋找最佳解決方案 嘗試將sessionCookiePath="/"屬性放入您的 context.xml 根節點:

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

這會將會話 cookie 的路徑設置為應用程序的根目錄,以便在重定向時傳遞。 這個簡單的修復對我有用。

許多人會建議 URL 編碼或將會話 ID 存儲在另一個 cookie 中,但根據我的理解,如果它適合您,這是最好的解決方案。 (會話 cookie 被認為是絕對必要的,因此按預期使用它們可能是最佳實踐。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM