我使用$.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(选项);});
其他回答
大多数给定的解决方案都使用一种变通方法,使用额外的头或不合适的HTTP代码。这些解决方案很可能会奏效,但感觉有点“粗糙”。我想出了另一个解决方案。
我们使用的WIF被配置为在401响应上重定向(passiveRedirectEnabled=“true”)。重定向在处理正常请求时是有用的,但对AJAX请求不起作用(因为浏览器不会执行302/重定向)。
使用global.asax中的以下代码,可以禁用AJAX请求的重定向:
void WSFederationAuthenticationModule_AuthorizationFailed(object sender, AuthorizationFailedEventArgs e)
{
string requestedWithHeader = HttpContext.Current.Request.Headers["X-Requested-With"];
if (!string.IsNullOrEmpty(requestedWithHeader) && requestedWithHeader.Equals("XMLHttpRequest", StringComparison.OrdinalIgnoreCase))
{
e.RedirectToIdentityProvider = false;
}
}
这允许您为AJAX请求返回401个响应,然后javascript可以通过重新加载页面来处理这些响应。重新加载页面将抛出一个401,由WIF处理(WIF将用户重定向到登录页面)。
处理401错误的示例javascript:
$(document).ajaxError(function (event, jqxhr, settings, exception) {
if (jqxhr.status == 401) { //Forbidden, go to login
//Use a reload, WIF will redirect to Login
location.reload(true);
}
});
我通过在login.php页面中放置以下内容来解决这个问题。
<script type="text/javascript">
if (top.location.href.indexOf('login.php') == -1) {
top.location.href = '/login.php';
}
</script>
我这样解决了这个问题:
添加一个中间件来处理响应,如果是对ajax请求的重定向,则使用重定向url将响应更改为正常响应。
class AjaxRedirect(object):
def process_response(self, request, response):
if request.is_ajax():
if type(response) == HttpResponseRedirect:
r = HttpResponse(json.dumps({'redirect': response['Location']}))
return r
return response
然后在ajaxComplete中,如果响应包含重定向,则它必须是重定向,因此请更改浏览器的位置。
$('body').ajaxComplete(function (e, xhr, settings) {
if (xhr.status == 200) {
var redirect = null;
try {
redirect = $.parseJSON(xhr.responseText).redirect;
if (redirect) {
window.location.href = redirect.replace(/\?.*$/, "?next=" + window.location.pathname);
}
} catch (e) {
return;
}
}
}
我在一个我正在修补的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在我完成我的回答后,立即通过了我的服务取消请求!
把弗拉基米尔·普拉德尼科夫和托马斯·汉森所说的话放在一起:
更改服务器端代码以检测它是否是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(选项);});