jQuery ajax 302跨域
一、ajax 302
ajax用于异步获取服务器数据,但是某天有这么一个使用场景:
> 基于安全考虑,登录的用户的信息失效时,系统的所有ajax接口都由服务器直接重定向到系统的登录页面,此时登录页面与系统属于同一个域;
于是否,使用ajaxComplete的方法为系统所有ajax统一设置请求完成后的回调,判断其http的status code是否为302,类似于下面代码:
$(document).ajaxComplete(function(e, xhr, settings){
var _location;
console.log(xhr);
if(xhr.status === 302){
_location = xhr.getResponseHeader("Location");
if(_location) {
location.assign(_location);
}
}
});
//获取数据的接口
$.ajax({
url: "/api/fetch.html"
}).always(function(ret){
console.log(ret);
});
可是测试结果显示,ajax的回调在重定向之后死活没有执行,直至获取重定向后的请求才会执行ajax的回调,也就是说重定向后的内容作为ajax的接口内容来响应
。此时可以看到浏览器控制台输出的ret
内容不是json字符串,实际上为系统重定向到登录页面的html字符串。
为什么会出现这样的结果呢?
在stackoverflow上可以找到讨论的答案:
> You can't handle redirects with XHR callbacks because the browser takes care of them automatically. You will only get back what at the redirected location.
也就是说,重定向是由浏览器自动透明的完成的。所以服务器将302响应发给浏览器时,浏览器并不是直接处理ajax的回调,而是先执行302重定向。这就是上面例子中为什么获取不到xhr.status为302的值。
一个ajax请求的重定向大致流程是这样的:
ajax --> browser --> server --> 302 --> browser(redirect) --> server --> browser --> ajax callback
注意,上面ajax获取不到xhr的status是有一个前提:即,服务器为response设置了*Location* header
。
因为,浏览器在发现Location的header时就会自动跳转到Location所指定的URL地址,类似于用js来进行重定向;不过这个重定向只有浏览器知道。
所以,在ajax接口返回302时,而没有设置Location的header时,这个xhr的status值还是能获取到的,下图是在浏览器控制台测试的结果:
可以看到服务器给response的header添加了Location1的header,浏览器并不认识,所以不会重定向,此时或可以获取xhr的status为302
二、ajax 302跨域
随着公司业务的发展新的情况出现了,公司要将登录认证统一到某台公共的服务器上,这时,失效的用户在ajax获取数据时状态失效而被重定向到登录页面;由于当前系统与登录页面不同域,而XHR不允许跨域访问数据,所以ajax的302也存在跨域问题。(不像页面之间重定向不存在这个问题,你可以访问当前系统的某个页面,服务可以重定向到www.baidu.com而不会有跨域问题)。
这时,由于存在跨域,浏览器不会进行重定向;但是能否通过上面的代码来用JavaScript进行重定向呢?
抱歉,同样不可以;这时通过ajaxComplete方法获取到的xhr的status值,发现其值为0,Location的header为null;所以这种办法行不通。更可取的方法可以是这样:
首先不要在服务器端进行重定向;然后通过接口的形式或者在response添加一个自定义header来区分重定向信息;最后由JavaScript来进行重定向
三、xhr status为0的问题
翻看W3C文档,发现xhr的status值由以下三个步骤来决定:
The status attribute must return the result of running these steps:
1. If the state is UNSENT or OPENED, return 0.
2. If the error flag is set, return 0.
3. Return the HTTP status code.
第二条的error flag:The error flag indicates some type of network error or fetch termination. It is initially unset.
通过上面得知:
在调用xhr的open方法还没有调用send方法,或者xhr出错了(如跨域就会发生网络错误)都会导致xhr state为0的情况
最常见的两种xhr status为0的情况:
ajax发送后还没有得到响应前立即刷新浏览器,这时ajax就会被浏览器给丢弃了,会返回status code为0;这主要发生在form表单的提交用ajax来提交,而没有阻止表单提交的默认行为,导致页面刷新,这时ajax发出了,但页面刷新; 其实ajax能得到xhr的status只不过值为0;
xhr跨域,包括异步请求跨域和302跨域的情况,这时会出现xhr status为0的情况
参考文献
jQuery ajax 302跨域的更多相关文章
- jquery ajax jsonp跨域调用实例代码
今天研究了AJAX使用JSONP进行跨域调用的方法,发现使用GET方式和POST方式都可以进行跨域调用,这里简单分享下,方便需要的朋友 客户端代码 复制代码 代码如下: <%@ Page Lan ...
- jquery ajax 无法跨域调用的解决办法
今天要用到jquery ajax 跨域调用,但是ajax是禁止跨域调用的,所以只能先在php文件使用函数取得跨域的值,然后用ajax调用本地php文件.
- 解决jquery ajax在跨域访问post请求的时候,ie9以下无效(包括ie9)的问题
最近在做项目的时候遇到一个问题,就是跨域请求ajax的时候ie9以下的浏览器不可以访问,直接执行error里面的代码,但是也不报错,就上网查了查,发现了一个很好用的方法,在这里记录一下,也希望可以帮到 ...
- jquery ajax在跨域访问post请求的时候,包括ie9以下的浏览器无效,其他浏览器正常
最近做的一个项目,原先没有要求兼容IE9以下,所以在写代码的时候也没有打开IE9以下去测试,这两天要去做IE9以下的兼容,在IE9以下打开本地的项目发现数据请求不成功,而通过发布道服务器上的链接打开是 ...
- jquery ajax CORS 跨域訪问 WebService
JS代码: var word = document.getElementById("word").value; $.ajax({ type: "POST", c ...
- jquery ajax在跨域访问post请求的时候,ie9以下无效(包括ie9)
1. 设置浏览器安全属性,启用[通过域访问数据源]选项,如图:
- JQuery+ajax+jsonp 跨域访问
Jsonp(JSON with Padding)是资料格式 json 的一种“使用模式”,可以让网页从别的网域获取资料. 关于Jsonp更详细的资料请参考http://baike.baidu.com/ ...
- PHP 支持 JQuery 的 JSONP 跨域访问
Jquery Ajax进行跨域时需要使用JSONP,但JSONP格式和JSON格式是有区别的,如果直接返回JSON格式就会报错 首先将原有的Jquery代码中的dataType改成“jsonp”,具体 ...
- jQuery的ajax jsonp跨域请求
了解:ajax.json.jsonp.“跨域”的关系 要弄清楚以上ajax.json.jsonp概念的关系,我觉得弄清楚ajax是“干什么的”,“怎么实现的”,“有什么问题”,“如果解决存在的问题”等 ...
随机推荐
- OneZero第三周第四次站立会议(2016.4.7)
1. 时间: 18:35--18:50 共计15分钟. 2. 成员: X 夏一鸣 * 组长 (博客:http://www.cnblogs.com/xiaym896/), G 郭又铭 (博客:http: ...
- canvas 实现掉落效果
var canvas = document.getElementById('canvas'); var cxt = canvas.getContext('2d'); cxt.strokeStyle = ...
- 23.Xcode中常用的快捷键操作
1.工程导航器:command+1 浏览文件夹,控制器,图片等 2.显示/隐藏导航器面板:Command+0 隐藏左边工具栏 3.显示/隐藏实用工具面板:Command+Option+0 使用工具面板 ...
- Our Future
The world is betting on how to win the football game: But I'm betting on how to win your heart: Mayb ...
- 2019.01.21 bzoj2441: [中山市选2011]小W的问题(树状数组+权值线段树)
传送门 数据结构优化计数菜题. 题意简述:给nnn个点问有多少个www型. www型的定义: 由5个不同的点组成,满足x1<x2<x3<x4<x5,x3>x1>x2 ...
- 2018.12.30 洛谷P4238 【模板】多项式求逆
传送门 多项式求逆模板题. 简单讲讲? 多项式求逆 定义: 对于一个多项式A(x)A(x)A(x),如果存在一个多项式B(x)B(x)B(x),满足B(x)B(x)B(x)的次数小于等于A(x)A(x ...
- 2018.11.09 bzoj1706: relays 奶牛接力跑(倍增+floyd)
传送门 倍增+floyd板子题. 先列出状态fi,j,kf_{i,j,k}fi,j,k表示经过iii条边从jjj到kkk的最短路. 然后发现可以用fi−1,j,kf_{i-1,j,k}fi−1,j, ...
- yii2 控制器渲染
render() : 渲染一个 视图名并使用一个 布局返回到渲染结果. renderPartial() : 渲染一个 视图名并且不使用布局. renderAjax() : 渲染一个 视图名并且不使用布 ...
- Linux 目录说解
目录 1.树状目录结构图 2./目录 3./etc/目录 4./usr/目录 5./var/目录 6./proc/目录 7./dev/目录 该文章主要来自于网络进行整理. 目录结构参考地址: http ...
- hashCode() 和equals() 区别和作用(转)
出处:https://www.jianshu.com/p/5a7f5f786b75 本章的内容主要解决下面几个问题: 1 equals() 的作用是什么? 2 equals() 与 == 的区别是什么 ...