我使用$.post()
使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div
元素。 但是,如果会话超时,服务器将发送重定向指令以将用户发送到登录页面。 在这种情况下,jQuery用登录页面的内容替换了div
元素,迫使用户的眼睛确实看到了一个罕见的场景。
如何使用jQuery 1.2.6从Ajax调用管理重定向指令?
#1楼
您还可以挂钩XMLHttpRequest发送原型。 这将适用于具有一个处理程序的所有发送(jQuery / dojo / etc)。
我编写了这段代码来处理500页的过期错误,但是它应该也可以捕获200个重定向。 准备好XMLHttpRequest上的Wikipedia条目onreadystatechange,以了解readyState的含义。
// Hook XMLHttpRequest
var oldXMLHttpRequestSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function() {
//console.dir( this );
this.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 500 && this.responseText.indexOf("Expired") != -1) {
try {
document.documentElement.innerHTML = this.responseText;
} catch(error) {
// IE makes document.documentElement read only
document.body.innerHTML = this.responseText;
}
}
};
oldXMLHttpRequestSend.apply(this, arguments);
}
#2楼
我只想分享我的方法,因为这可能会帮助某人:
我基本上包括一个JavaScript模块,该模块处理身份验证之类的内容,例如显示用户名,在这种情况下,还处理重定向到登录页面的情况 。
我的情况:我们基本上有一个ISA服务器,在这两个服务器之间侦听所有请求, 并以302和登录页面的位置标头作为响应 。
在我的JavaScript模块中,我最初的方法是
$(document).ajaxComplete(function(e, xhr, settings){
if(xhr.status === 302){
//check for location header and redirect...
}
});
问题(这里已经提到了很多问题)是浏览器自己处理重定向,因此我的ajaxComplete
回调从未被调用过,而是得到了已经重定向的Login页面的响应 ,显然是status 200
。 问题:您如何检测成功的200响应是您的实际登录页面还是其他任意页面?
解决方案
由于无法捕获302重定向响应,因此在登录页面上添加了LoginPage
标头,其中包含登录页面本身的URL。 现在,在模块中,我侦听标头并进行重定向:
if(xhr.status === 200){
var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage");
if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){
window.location.replace(loginPageRedirectHeader);
}
}
...就像魅力:)。 您可能想知道为什么我将URL包含在LoginPage
标头中...基本上是因为我找不到确定从xhr
对象进行自动位置重定向而导致的GET
...
#3楼
弗拉基米尔·普鲁德尼科夫和托马斯·汉森说的话:
- 更改服务器端代码以检测它是否为XHR。 如果是,请将重定向的响应代码设置为278。在django中:
if request.is_ajax(): response.status_code = 278
这使浏览器将响应视为成功,并将其交给Javascript。
- 在您的JS中,确保通过Ajax提交表单,检查响应代码并根据需要重定向:
$('#my-form').submit(function(event){ event.preventDefault(); var options = { url: $(this).attr('action'), type: 'POST', complete: function(response, textStatus) { if (response.status == 278) { window.location = response.getResponseHeader('Location') } else { ... your code here ... } }, data: $(this).serialize(), }; $.ajax(options); });
#4楼
我认为处理此问题的更好方法是利用现有的HTTP协议响应代码,尤其是401 Unauthorized
。
这是我解决的方法:
- 服务器端:如果会话过期,并且请求是ajax。 发送401响应码标头
客户端:绑定到ajax事件
$('body').bind('ajaxSuccess',function(event,request,settings){ if (401 == request.status){ window.location = '/users/login'; } }).bind('ajaxError',function(event,request,settings){ if (401 == request.status){ window.location = '/users/login'; } });
IMO这是更通用的,您没有编写新的自定义规范/标题。 您也不必修改任何现有的ajax调用。
编辑:根据下面的@Rob的注释,401(身份验证错误的HTTP状态代码)应作为指示符。 有关更多详细信息,请参见403禁止与401未经授权的HTTP响应 。 话虽如此,某些Web框架同时使用403进行身份验证和授权错误-因此请进行相应调整。 谢谢罗伯。
#5楼
如果您还想传递值,那么还可以设置会话变量并访问Eg:在您的jsp中,您可以编写
<% HttpSession ses = request.getSession(true);
String temp=request.getAttribute("what_you_defined"); %>
然后,您可以将此临时值存储在javascript变量中,然后进行操作
#6楼
头文件解决方案没有任何成功-我的ajaxSuccess / ajaxComplete方法中从未将它们拾取。 我在自定义响应中使用了Steg的答案,但在JS方面做了一些修改。 我设置了在每个函数中调用的方法,因此可以使用标准的$.get
和$.post
方法。
function handleAjaxResponse(data, callback) {
//Try to convert and parse object
try {
if (jQuery.type(data) === "string") {
data = jQuery.parseJSON(data);
}
if (data.error) {
if (data.error == 'login') {
window.location.reload();
return;
}
else if (data.error.length > 0) {
alert(data.error);
return;
}
}
}
catch(ex) { }
if (callback) {
callback(data);
}
}
使用中的示例...
function submitAjaxForm(form, url, action) {
//Lock form
form.find('.ajax-submit').hide();
form.find('.loader').show();
$.post(url, form.serialize(), function (d) {
//Unlock for