作为一个前端er,跨域这方面的知识是必须掌握的,只是说究竟是完全理解透了还是只是在会用这个层面。
我的目标是把它理解透了,只有这样才能在碰到很复杂的问题时不至于无从下手。

跨域是个啥

在上一篇文章里,我说了从输入一个url到回车究竟发生了什么,读过就知道实际上浏览器是从服务器上获取文件然后进行渲染解析等操作,按照这个过程,我浏览器是不是只要有地址就随便取别人服务器上的东西呢?
答案是否定的,相信作为一个从业者你也能想到,这一定会带来一些安全问题,浏览器自然也想到了,所以很久以前Netscape就提出了同源策略,定义是:

同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。

那么现在就有一个问题了,同源同源,那这个源到底是个啥玩意?
其实,源是由URI,主机名,端口号组合而成的。

所以可想而知,在下面几种情况下资源不符合同源策略:

  1. 不同域名,如:http://www.hankqin.comhttp://www.qinhank.com
  2. 相同域名不同端口号,如:http://www.hankqin.com:8080http://www.hankqin.com:8081
  3. 同一个域名不同协议
  4. 主域和子域,如http://www.hankqin.comhttp://blog.hankqin.com
  5. 子域和子域,如http://blog.hankqin.comhttp://page.hankqin.com

基于以上,跨域的定义也就自然出来了:

跨域,指的是浏览器不能执行其他网站的脚本。

解决跨域

知道了问题所在,就需要针对它做出相应的解决方案了。
常见的解决方案有:

  1. JSONP
  2. 跨域资源共享(CORS)
  3. document.domain+iframe(适用于主域名相同的情况)
  4. window.name + iframe
  5. postMessage(适用于两个iframe或两个页面之间)
  6. location.hash + iframe(适用于两个iframe之间)

JSONP

这个方案我想应该是目前用的最多的。它的原理很简单:
作为从业者基本都知道script、img、link标签实际上使用的是开发策略,所以实际上我们是可以随便引用非同源的脚本的,JSONP就是基于这个策略实现的,具体过程如下:

  1. 前后端约定特定字符为JSONP返回(一般使用callback)
  2. 定义一个全局可访问的函数,参数即为服务器返回的数据,如:jsonpFn(data){}
  3. 通过script标签执行函数,如:
    1
    <script src="http://baidu.com?callback=jsonpFn&data=getJsonpData"></script>

自此,跨域完成,数据成功返回并运行。
但正如你所见,JSONP只支持GET方法,对于POST是无力的。

CORS

即跨域资源共享,关于这个更详细的说明请看阮一峰老师的跨域资源共享 CORS 详解
作为前端,实际上在CORS中需要做的不多,主要是后端。
浏览器CORS请求分成两种:

  1. 简单请求
  2. 协商模型/预检请求(Preflighted Request),即非简单请求

这两种有什么分别呢,又是怎么区分呢?
一般来说,只要满足亮点,那它就是简单请求,否则则为非简单请求:

  1. 请求方式为GETPOSTHEAD
  2. HTTP的头信息子段
  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain,其中’text/plain’默认支持,其他两种则需要预检请求和服务器协商。

其余的我不太想说了,实际应用中都会有些不够完美。
更多细节请狂点我查看