首页 > 代码库 > JSONP && CORS

JSONP && CORS

  前天面试被问到了跨域的问题,自我感觉回答的并不理想,下面我就分享一下整理后的总结分享给大家

一、为什么要跨域

  安全限制

  JavaScript或Cookie只能访问同域下的内容——同源策略

  同源策略

  下表相对于: http://h5.jd.com/dir/ajax.js

  技术分享

 

  注意

  • 协议和端口造成的跨域问题,非前端解决范畴
  • 所谓域,是通过“url首部”来识别,而非判断域与ip的对应关系

  (“URL的首部”指window.location.protocol +window.location.host)

二、跨域方案

1. jsonp

  详见博客 JSON 和 JSONP两兄弟

2. cors

方案对比
  JSONP CORS
目的 跨域 跨域
支持

get

(受IE下url长度不能超过2083个字节的限制和出于安全考虑,一般不用来提交数据)

所有类型的http请求
支持度 包括老式浏览器 不支持部分浏览器,移动端支持很好
缺点

1)安全问题(请求代码中可能存在安全隐患)

2)确定jsonp请求是否失败不太容易

3)只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题

支持率
原理

被包含在一个回调函数中的JSON

核心则是动态添加<script>标签来调用服务器提供的js脚本

(允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了)

使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败

(只需由服务器发送一个响应标头即可)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CORS需要浏览器和服务器同时支持

实现CORS通信的关键是服务器,只要服务器实现了CORS接口,就可以跨域通信


1)两种请求方式

  简单请求、非简单请求

  a)简单请求:

  技术分享

  

  跨域时,浏览器自动在头部信息中添加一个origin 字段(指定请求源-协议+域名+端口),如下图所示

  技术分享

  服务器判断origin在域名许可范围内,返回响应:

  技术分享

  若不存在 Access-Control-Allow-Origin 字段,则出错

  以上头部信息中,CORS相关字段有

  • Access-Control-Allow-Origin
    必须字段,其值为 origin / *(可接受任意域名请求)
  • Access-Control-Allow-Credentials
    可选,是否允许发送Cookie
  • Access-Control-Expose-Headers
    可选,是否需要Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma之外的字段

  withCredentials 属性

   CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段

Access-Control-Allow-Credentials: true

 

  另一方面,开发者必须在AJAX请求中打开withCredentials属性。

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

 

  注意

  如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。

  b)非简单请求(不同时满足以上条件)

  请求方法是PUTDELETE,或者Content-Type字段的类型是application/json

   浏览器对于非简单请求,就自动发出一个"预检"请求,要求服务器确认可以这样请求。下面是这个"预检"请求的HTTP头信息

  技术分享

  

  除了Origin字段,"预检"请求的头信息包括两个特殊字段。

  • Access-Control-Request-Method

   该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT

  • Access-Control-Request-Headers

   该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header

 

2.CORS 支持度

 技术分享

 

3. iframe

 (只有在主域相同时才能使用)

  1)www.a.com/a.html中:

document.domain = ‘a.com‘;
var ifr = document.createElement(‘iframe‘);
ifr.src = http://www.mamicode.com/‘http://www.script.a.com/b.html‘;
ifr.display = none;
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    //在这里操作doc,也就是b.html
    ifr.onload = null;
};

 

  2) 在www.script.a.com/b.html中:

document.domain = ‘a.com‘;

 

其他跨域方案

window.name:

在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。

window.postMessage:

该方法是 HTML5 新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

动态创建script

JSONP也就是利用这个原理。

利用iframe和location.hash

淘汰类技术

利用flash

淘汰类技术

 

参考链接:

http://tech.jandou.com/cross-domain.html

http://www.cnblogs.com/JChen666/p/3399951.html

http://www.ruanyifeng.com/blog/2016/04/cors.html

 

 

  

 

JSONP && CORS