会话属性在调用客户端重定向后丢失
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
中保存的会话属性?
编辑
下面是我用来保存session属性的代码片段。
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 (例如,在会话创建时,服务器响应一个编码会话ID的cookie,而在服务器端,您期望cookie将每个请求与现有会话相关联)。
客户端有责任确保他们以服务器期望的方式参与会话。当使用Java Servlet API实现服务器时,它要么是jsessionid cookie,要么是与URL附加相同名称的查询参数,该URL标识会话id。
如果客户端不支持cookie,使用Java Servlet API您将不得不重定向到HttpServletResponse.encodeRedirectURL(String url)
创建的URL。
为了从servlet重定向使用HttpServletResponse.sendRedirect(String url);
.
用标准的HTTP重定向响应服务器将简化您的设计。Jquery确实实现了这些标准,因此将尊重来自服务器的HTTP 301和302响应,如图所示,因此客户端不需要重定向逻辑。
客户端
您的客户端是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被认为是绝对必要的,因此按预期使用它们可能是最佳实践。)
- ajax表单提交后从客户端重定向
- 在重定向到 ASP.NET C# 中的另一个页面之前显示客户端脚本警报
- Ember-cli-Mirage 重定向 socket.io 客户端,该客户端注入 Mirage 中
- 遵循重定向的图像HTTP请求,客户端
- 在进行客户端重定向时,是否可以向服务器发送一些JSON
- 在 iframe 中重定向服务器端加载
- 使用javascript进行非www到www客户端重定向
- 根据客户选择的产品重定向客户
- 雅虎身份验证通过OAuth没有任何重定向(客户端).这可能吗?
- 会话属性在调用客户端重定向后丢失
- 客户端重定向使用地址栏参数
- NodeJS:将客户端重定向到另一个Worker/Instance
- 在使用Express执行函数时重定向客户端
- 如何在Meteor中重定向到外部URL并收集客户端数据
- 客户端重定向问题
- 用php编写一个客户端重定向服务器端
- 当我们使用301重定向时如何收集客户端数据
- 如何从客户端手动调用django中的重定向函数
- 是否可以使用JavaScript获取客户端上给定链接的重定向链中的所有URL
- 仅使用客户端代码检测301重定向