~ Ajax 跨域
Ajax 跨域的原理
Ajax 跨域问题,主要是因为浏览器的同源政策?!。首先要理解“源”的概念,可以通过「协议+域名+端口」确定一个源。
简单来讲,可以把一个项目理解为一个源。Ajax 请求可以对源内的资源发起访问,但不同源之间进行 Ajax 就会有问题。
当向不同源的资源发起 Ajax 请求时, 浏览器会加上 Origin 字段来标识源。
Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Connection: keep-alive Content-Length: 8 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Host: localhost:7070 Origin: http://localhost:9090 协议+域名+端口服务器会根据 Origin 字段决定是否同意这次请求, 如果 Origin 指定的源不在许可范围内, 服务器会返回一个不带有Access-Control-Allow-Origin 字段的响应. 浏览器解析时发现缺少了这个字段, 就会报错。
[ Ajax 跨域的表现?! ] 这种错误不能通过状态码识别, 因为状态码很有可能就是 200。
Ajax 跨域解决方案
// 同源政策规定,AJAX 请求只能发给同源的网址,否则就报错。
除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),还可以采用以下几种方式:
由于接口代理是有代价的,所以其仅是在开发过程中进行的。
与其他方法不同,CORS 是后端解决,而代理请求的方式主要是前端对接口进行代理,即:
- 前端 Ajax 请求对是本地接口;
- 本地接口接收到请求后向实际的接口请求数据,然后再将信息返回给前端;
- 一般用 Node.js 或 Nginx 即可代理。
[1] CORS?! // CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。
它是 W3C 标准,是跨源 AJAX 请求的根本解决方法。相比 JSONP 只能发
GET请求,CORS 允许任何类型的请求。
[2] JSONP // 原理:script 元素的 src 属性不受同源政策限制,可以跨域请求(即,拥有跨域能力)
JSONP 是服务器与客户端跨源通信的常用方法,其特点是:简单适应,支持低版本浏览器,且服务器改动非常小。
[ 注意 ] 基于 JSONP 的实现原理,所以 JSONP 只能是“GET”请求,不能进行较为复杂的POST和其他请求,所以遇到类似的情况,就需要考虑跨域资源共享 CORS 或其他方案了。
它的基本思想是,网页通过添加一个 script 元素,向服务器请求 JSON 数据,这种做法不受同源政策限制,服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
[ 实现步骤 ] 首先,网页动态插入 script 元素,由它向跨域网址发送请求(请求 JSON 数据)。
function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function () { addScriptTag('http://example.com/ip?callback=foo'); } function foo(data) { console.log('response data: ' + JSON.stringify(data)); }; // 请求时,接口地址是作为构建出的脚本标签的src的,这样,当脚本标签构建出来时,最终的src是接口返回的内容上述代码通过动态添加 script 元素,向服务器 example.com 发出请求。需注意的是,该请求的查询字符串有一个 callback 参数,用来指定回调函数的名称,这对于 JSONP 是必需的。
服务器收到这个请求后,会将数据放在回调函数的参数位置返回。
// 服务端对应的接口在返回参数外面添加函数包裹层 foo({ "test": "testData" });由于 script 元素请求的脚本,直接作为代码运行,所以,只要浏览器定义了 foo 函数,该函数就会立即调用。作为参数的 JSON 数据被视为 JS 对象,而不是字符串,因此避免了使用 JSON.parse 的步骤。
[ 在 jQuery 中使用 JSONP ] 在 jQuery 中使用 jsonp 技术,可以使用 ajax() 方法:
JQuery 对前台做了很好的处理,如自动生成全局回调函数等,但后台还需要开发人员自己实现。
// 前端内容 $.ajax({ type:'get', url:"http://xxx.com/demo/jsonp.php", // url:"http://xxx.com/demo?callback=foo" dataType:"jsonp", //必须指定 // jsonp : "callback", //自定义参数名称(等号前面的),若不指定则默认为callback // jsonpCallback:"foo",// 自定义回调函数的名字(等号后面的),若不指定则Jquery自己生成随机的名称 success:function(data){ console.log(data.username,data.password); } }); // 请求URL http://xxx.com/demo?callback=foo // 后端内容 <?php $cb = $_GET['callback']; $arr = array("username"=>"zhangsan","password"=>"123"); echo $cb.'('.json_encode($arr)')'; ?>当 dataType 为 JSONP 时,jQuery 会为用户生成一个全局函数名称为 jsonpCallback 参数的值,这个函数内部调用了success 方法 jQuery 的实现原理及步骤;
以 GET 方式请求目标地址,并在 URL 中拼接以 jsonp 参数值为 key,以 jsonpCallback 值为 value 的参数;
请求返回回调函数数据;
触发调用全局的回调函数,在全局函数回调中调用 success 方法并将数据传递给 success 方法。


