$.ajax({//.... other definitioncomplete:function(xmlHttp){if(xmlHttp.status.toString()[0]=='3'){top.location.href = xmlHttp.getResponseHeader('Location');}});
$.ajax({type: "POST",url: reqUrl,data: reqBody,dataType: "json",success: function(data, textStatus) {if (data.redirect) {// data.redirect contains the string URL to redirect towindow.location.href = data.redirect;} else {// data.form contains the HTML for the replacement form$("#myform").replaceWith(data.form);}}});
// redirect ajax requests that are redirected, not found (404), or forbidden (403.)$('body').bind('ajaxComplete', function(event,request,settings){switch(request.status) {case 301: case 404: case 403:window.location.replace("http://mysite.tld/login");break;}});
IMO this is more generic and you are not writing some new custom spec/header. You also should not have to modify any of your existing ajax calls.
Edit: Per @Rob's comment below, 401 (the HTTP status code for authentication errors) should be the indicator. See 403 Forbidden vs 401 Unauthorized HTTP responses for more detail. With that being said some web frameworks use 403 for both authentication AND authorization errors - so adapt accordingly. Thanks Rob.
function handleAjaxResponse(data, callback) {//Try to convert and parse objecttry {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 formform.find('.ajax-submit').hide();form.find('.loader').show();
$.post(url, form.serialize(), function (d) {//Unlock formform.find('.ajax-submit').show();form.find('.loader').hide();
handleAjaxResponse(d, function (data) {// ... more code for if auth passes ...});});return false;}
$(document).ajaxError(function (event, jqxhr, settings, exception) {
if (jqxhr.status == 401) { //Forbidden, go to login//Use a reload, WIF will redirect to Loginlocation.reload(true);}});
在任何Ajax请求上,我的服务器都会返回一个Json 200响应“NEED TO AUTHENTICATE”(如果客户端需要进行身份验证)。
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";
@Overridepublic 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());}}}
public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
public CustomLoginUrlAuthenticationEntryPoint(final String loginFormUrl) {super(loginFormUrl);}
// For AJAX requests for user that isn't logged in, need to return 403 status.// For normal requests, Spring does a (302) redirect to login.jsp which the browser handles normally.@Overridepublic void commence(final HttpServletRequest request,final HttpServletResponse response,final AuthenticationException authException)throws IOException, ServletException {if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");} else {super.commence(request, response, authException);}}}