我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。
如何使用jQuery1.2.6管理Ajax调用的重定向指令?
我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。
如何使用jQuery1.2.6管理Ajax调用的重定向指令?
当前回答
有些人可能会发现以下内容很有用:
我希望客户机被重定向到登录页面,以执行在没有授权令牌的情况下发送的任何rest操作。由于我的所有其余操作都是基于Ajax的,所以我需要一种很好的通用方法来重定向到登录页面,而不是处理Ajax成功函数。
这是我所做的:
在任何Ajax请求中,我的服务器都会返回Json 200响应“需要认证”(如果客户端需要认证)。
Java(服务器端)中的简单示例:
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
private final Logger m_logger = LoggerFactory.getLogger(AuthenticationFilter.class);
public static final String COOKIE_NAME = "token_cookie";
@Override
public void filter(ContainerRequestContext context) throws IOException {
// Check if it has a cookie.
try {
Map<String, Cookie> cookies = context.getCookies();
if (!cookies.containsKey(COOKIE_NAME)) {
m_logger.debug("No cookie set - redirect to login page");
throw new AuthenticationException();
}
}
catch (AuthenticationException e) {
context.abortWith(Response.ok("\"NEED TO AUTHENTICATE\"").type("json/application").build());
}
}
}
在我的Javascript中,我添加了以下代码:
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
var originalSuccess = options.success;
options.success = function(data) {
if (data == "NEED TO AUTHENTICATE") {
window.location.replace("/login.html");
}
else {
originalSuccess(data);
}
};
});
就这样。
其他回答
后端弹簧@ExceptionHandler。
400和业务相关异常的错误字符串(将在弹出窗口中显示)302和用于浏览器请求的应用程序异常的错误/登录页面的位置标头(由浏览器自动重定向)500/400和错误/登录页面的位置头,用于通过ajax回调重定向ajax请求
通过用户会话将异常详细信息传递到错误页
@Order(HIGHEST_PRECEDENCE)
public class ExceptionHandlerAdvise {
private static Logger logger = LoggerFactory.getLogger(ExceptionHandlerAdvise.class);
@Autowired
private UserInfo userInfo;
@ExceptionHandler(value = Exception.class)
protected ResponseEntity<Object> handleException(Exception ex, WebRequest request) {
HttpHeaders headers = new HttpHeaders();
if (isBusinessException(ex)) {
logger.warn(getRequestURL(request), ex);
return new ResponseEntity<>(getUserFriendlyErrorMessage(ex), headers, BAD_REQUEST);
} else {
logger.error(getRequestURL(request), ex);
userInfo.setLastError(ex);
headers.add("Location", "/euc-portal/fault");
return new ResponseEntity<>(null, headers, isAjaxRequest(request) ? INTERNAL_SERVER_ERROR : FOUND);
}
}
}
private boolean isAjaxRequest(WebRequest request) {
return request.getHeader("x-requested-with") != null;
}
private String getRequestURL(WebRequest request) {
if (request instanceof ServletWebRequest) {
HttpServletRequest servletRequest = ((ServletWebRequest) request).getRequest();
StringBuilder uri = new StringBuilder(servletRequest.getRequestURI());
if (servletRequest.getQueryString() != null) {
uri.append("?");
uri.append(servletRequest.getQueryString());
}
return uri.toString();
}
return request.getContextPath();
}
登录手柄接口
@Service
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Autowired
private UserInfo userInfo;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (userInfo.getPrincipal() == null && !(request.getRequestURI().contains(LOGIN_URL) || request.getRequestURI().contains(FAULT_URL) || request.getRequestURI().startsWith("/app/css"))) {
response.addHeader("Location", LOGIN_URL);
response.setStatus(isAjaxRequest(request) ? BAD_REQUEST.value() : FOUND.value());
return false;
}
return true;
}
}
客户端代码
$.post('/app/request', params).done(function(response) {
...
}).fail(function(response) {
if (response.getResponseHeader('Location')) {
window.top.location.href = response.getResponseHeader('Location');
return;
}
alert(response);
});
把弗拉基米尔·普拉德尼科夫和托马斯·汉森所说的话放在一起:
更改服务器端代码以检测它是否是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(选项);});
有些人可能会发现以下内容很有用:
我希望客户机被重定向到登录页面,以执行在没有授权令牌的情况下发送的任何rest操作。由于我的所有其余操作都是基于Ajax的,所以我需要一种很好的通用方法来重定向到登录页面,而不是处理Ajax成功函数。
这是我所做的:
在任何Ajax请求中,我的服务器都会返回Json 200响应“需要认证”(如果客户端需要认证)。
Java(服务器端)中的简单示例:
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
private final Logger m_logger = LoggerFactory.getLogger(AuthenticationFilter.class);
public static final String COOKIE_NAME = "token_cookie";
@Override
public void filter(ContainerRequestContext context) throws IOException {
// Check if it has a cookie.
try {
Map<String, Cookie> cookies = context.getCookies();
if (!cookies.containsKey(COOKIE_NAME)) {
m_logger.debug("No cookie set - redirect to login page");
throw new AuthenticationException();
}
}
catch (AuthenticationException e) {
context.abortWith(Response.ok("\"NEED TO AUTHENTICATE\"").type("json/application").build());
}
}
}
在我的Javascript中,我添加了以下代码:
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
var originalSuccess = options.success;
options.success = function(data) {
if (data == "NEED TO AUTHENTICATE") {
window.location.replace("/login.html");
}
else {
originalSuccess(data);
}
};
});
就这样。
使用ASP.NET MVC RedirectToAction方法可能会出现此问题。为了防止表单在div中显示响应,您可以简单地使用$.ajaxSetup对响应进行某种ajax响应过滤。如果响应包含MVC重定向,则可以在JS端评估此表达式。JS的示例代码如下:
$.ajaxSetup({
dataFilter: function (data, type) {
if (data && typeof data == "string") {
if (data.indexOf('window.location') > -1) {
eval(data);
}
}
return data;
}
});
如果数据为:“window.location='/Acount/Login'”,则过滤器将捕捉到该数据并进行评估以进行重定向,而不是让数据显示。
使用低级$.ajax()调用:
$.ajax({
url: "/yourservlet",
data: { },
complete: function(xmlHttp) {
// xmlHttp is a XMLHttpRquest object
alert(xmlHttp.status);
}
});
尝试此操作进行重定向:
if (xmlHttp.code != 200) {
top.location.href = '/some/other/page';
}