我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。
如何使用jQuery1.2.6管理Ajax调用的重定向指令?
我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。
如何使用jQuery1.2.6管理Ajax调用的重定向指令?
当前回答
把弗拉基米尔·普拉德尼科夫和托马斯·汉森所说的话放在一起:
更改服务器端代码以检测它是否是XHR。如果是,则将重定向的响应代码设置为278。在django:
如果request.is_ajax():响应状态代码=278
这使得浏览器将响应视为成功,并将其交给您的Javascript。
在JS中,确保通过Ajax提交表单,检查响应代码并根据需要重定向:
$(“#my form”).submit(函数(事件){event.prpreventDefault();var选项={url:$(this).attr('action'),类型:'POST',complete:函数(响应,textStatus){如果(response.status==278){window.location=响应.getResponseHeader(“位置”)}否则{…您的代码在这里…}},data:$(this).serialize(),}; $.ajax(选项);});
其他回答
此外,您可能希望将用户重定向到给定的标头URL。因此,最终将如下所示:
$.ajax({
//.... other definition
complete:function(xmlHttp){
if(xmlHttp.status.toString()[0]=='3'){
top.location.href = xmlHttp.getResponseHeader('Location');
}
});
UPD:机会。有相同的任务,但不起作用。做这些事。当我找到解决方案时,我会给你看。
我知道这个话题已经过时了,但我将给出另一种我已经发现并在这里描述过的方法。基本上,我使用的是ASP.MVC和WIF(但这对于本主题的上下文来说并不重要——无论使用哪种框架,答案都是足够的。线索保持不变——在执行ajax请求时处理与身份验证失败相关的问题)。
下面显示的方法可以应用于所有开箱即用的ajax请求(如果它们显然没有重新定义beforeEnd事件)。
$.ajaxSetup({
beforeSend: checkPulse,
error: function (XMLHttpRequest, textStatus, errorThrown) {
document.open();
document.write(XMLHttpRequest.responseText);
document.close();
}
});
在执行任何ajax请求之前,调用CheckPulse方法(可以是任何最简单的控制器方法):
[Authorize]
public virtual void CheckPulse() {}
如果用户未经身份验证(令牌已过期),则无法访问该方法(受Authorize属性保护)。因为框架在令牌过期时处理身份验证,所以它将http状态302置于响应中。如果您不希望浏览器透明地处理302响应,请在Global.asax中捕获它,并将响应状态更改为200 OK。此外,添加header,它指示您以特殊方式处理此类响应(稍后在客户端):
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 302
&& (new HttpContextWrapper(Context)).Request.IsAjaxRequest())
{
Context.Response.StatusCode = 200;
Context.Response.AddHeader("REQUIRES_AUTH", "1");
}
}
最后在客户端检查这样的自定义头。如果存在,则应该完成到登录页面的完全重定向(在我的情况下,window.location被来自请求的url替换,该url由我的框架自动处理)。
function checkPulse(XMLHttpRequest) {
var location = window.location.href;
$.ajax({
url: "/Controller/CheckPulse",
type: 'GET',
async: false,
beforeSend: null,
success:
function (result, textStatus, xhr) {
if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') {
XMLHttpRequest.abort(); // terminate further ajax execution
window.location = location;
}
}
});
}
我对标题解决方案没有任何成功——它们从未在我的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 form
form.find('.ajax-submit').show();
form.find('.loader').hide();
handleAjaxResponse(d, function (data) {
// ... more code for if auth passes ...
});
});
return false;
}
我在一个我正在修补的django应用程序上遇到了这个问题(免责声明:我正在修补以学习,绝不是专家)。我想做的是使用jQueryajax向资源发送DELETE请求,在服务器端删除它,然后(基本上)将重定向返回主页。当我从python脚本发送HttpResponseRedirect('/theRedirect/')时,jQuery的ajax方法收到的是200而不是302。因此,我所做的是发送一个300的回复,其中包括:
response = HttpResponse(status='300')
response['Location'] = '/the-redirect/'
return response
然后,我使用jQuery.ajax在客户端上发送/处理请求,如下所示:
<button onclick="*the-jquery*">Delete</button>
where *the-jquery* =
$.ajax({
type: 'DELETE',
url: '/resource-url/',
complete: function(jqxhr){
window.location = jqxhr.getResponseHeader('Location');
}
});
也许使用300并不“正确”,但至少它的工作方式和我想的一样。
PS:这是一个巨大的痛苦,在移动版SO上编辑。愚蠢的ISP在我完成我的回答后,立即通过了我的服务取消请求!
在servlet中,您应该将response.setStatus(response.SC_MOVED_PERMANENTLY);要发送重定向所需的“301”xmlHttp状态。。。
在$.ajax函数中,不应使用.toString()函数。。。,只是
如果(xmlHttp.status==301){top.location.href='xxxx.jsp';}
问题是它不是很灵活,你无法决定要重定向到哪里。。
通过servlet重定向应该是最好的方法。但我仍然找不到正确的方法。