我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。
如何使用jQuery1.2.6管理Ajax调用的重定向指令?
我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。
如何使用jQuery1.2.6管理Ajax调用的重定向指令?
当前回答
我对标题解决方案没有任何成功——它们从未在我的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;
}
其他回答
没有浏览器正确处理301和302响应。事实上,标准甚至说他们应该“透明”地处理它们,这对于Ajax库供应商来说是一个非常头疼的问题。在RaAjax中,我们被迫使用HTTP响应状态代码278(只是一些“未使用”的成功代码)来透明地处理来自服务器的重定向。。。
这真的让我很恼火,如果这里有人对W3C有一些“吸引力”,我会很感激你能让W3C知道我们确实需要自己处理301和302代码…!;)
如果您使用的是Spring Security,答案似乎对人们有用,但我发现扩展LoginUrlAuthenticationEntryPoint并添加特定代码来处理AJAX更为健壮。大多数示例拦截所有重定向,而不仅仅是身份验证失败。这对于我所从事的项目来说是不可取的。如果不希望缓存失败的AJAX请求,您可能会发现还需要扩展ExceptionTranslationFilter并重写“sendStartAuthentication”方法以删除缓存步骤。
示例AjaxAwareAuthenticationEntryPoint:
public class AjaxAwareAuthenticationEntryPoint extends
LoginUrlAuthenticationEntryPoint {
public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
super(loginUrl);
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
if (isAjax(request)) {
response.sendError(HttpStatus.UNAUTHORIZED.value(), "Please re-authenticate yourself");
} else {
super.commence(request, response, authException);
}
}
public static boolean isAjax(HttpServletRequest request) {
return request != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
}
}
来源:1, 2
我有一个适合我的简单解决方案,无需更改服务器代码。。。只要加一茶匙肉豆蔻。。。
$(document).ready(function ()
{
$(document).ajaxSend(
function(event,request,settings)
{
var intercepted_success = settings.success;
settings.success = function( a, b, c )
{
if( request.responseText.indexOf( "<html>" ) > -1 )
window.location = window.location;
else
intercepted_success( a, b, c );
};
});
});
我检查了html标记的存在,但您可以更改indexOf以搜索登录页面中存在的任何唯一字符串。。。
您还可以钩住XMLHttpRequest发送原型。这将使用一个处理程序处理所有发送(jQuery/dojo/etc)。
我编写这段代码是为了处理一个500页的过期错误,但它应该可以捕获200个重定向。准备好有关readyState含义的XMLHttpRequest onreadystatechange上的维基百科条目。
// 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);
}
这对我有用:
success: function(data, textStatus, xhr) {
console.log(xhr.status);
}
一旦成功,ajax将获得浏览器从服务器获得的相同状态代码并执行它。