# 同源策略

# 什么是同源

源(origin)是指协议、域名和端口号。若地址里面的协议、域名和端口号均相同则属于同源。三者有一个不相同则代表着不同源

相对于http://www.uek.com/index.html做同源检测:

地址 结果
http://www.uek.com/test/a.html 同源
https://www.uek.com/index.html 协议不同
http://www.uekedu.com/index.html 主机名不同
http://www.uek.com:8080/index.html 端口号不同

# IE 例外

  1. 两个相互之间高度互信的域名,不遵守同源策略的限制。
  2. IE 未将端口号加入到同源策略的组成部分之中

# 同源策略

同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。

# 跨域

# 跨域限制的必要性

上面提到浏览器的同源策略是为了安全。跨域主要存在两方面安全问题

  1. DOM 同源策略
    我们用一个iframe把银行的网站嵌套在我们的网页上,这样的话,我们的网站和银行的网站除了域名没有其他的区别,如果没有同源策略,用户操作网页,我们就可以通过我们自己的网站跨域来访问银行的dom节点,从而拿到用户的信息。
  2. XMLHttpRequest 同源策略
    用户访问银行的网站,银行在用户的客户端中cookie中添加标识。用户再访问恶意网站,如果没有同源策略,恶意网站就会向银行网站发送恶意的ajax请求,请求会把银行给用户cookie中添加的标识发送过去,银行网站识别到正确的cookie返回请求数据,这样数据就会泄漏

# 跨域问题的解决办法

# jsonp(与json并没有什么关系)

在a.com的html页面里创建一个回调函数fun,动态添加<script>元素,向服务器发送请求,请求地址后面加上查询字符串,通过callback参数指定回调函数的名字。请求地址为http://b.com/main.js?callback=fun。在main.js中调用这个回调函数fun,并且以JSON数据形式作为参数传递,在a.com通过调用fun中接收参数。

利用script标签没有跨域限制的特点

# 缺点

  1. 只能使用GET请求
  2. 不能很好的发现错误,并进行处理。

# 服务器代理

服务器端不存在跨域的问题,所以可以用服务器代理的方式来解决跨域问题。
让自己的服务器去访问另一个服务器,然后再把数据从我们自己的服务器上返回到页面。
A客户端(浏览器) ==> A服务器 ==> B服务器 ==> A客户端(浏览器)

# CORS 的实现

CORS(跨源资源共享)是一个系统,由传输HTTP标头组成,用于确定浏览器是否阻止前端JavaScript代码访问跨源请求的响应。

Access-Control-Allow-Origin: http://www.xxx.com      //允许从http://www.xxx.com源请求代码来访问资源。 *代表允许所有的
Access-Control-Allow-Methods:PUT,POST,GET,DELETE,OPTIONS       //允许哪些请求方法
Access-Control-Allow-Headers:<header-name> [<header-name> ] *   //请求需要具有的标头

# window.name+iframe

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
在我们的当前页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取数据页面的数据,并把数据存放到window.name上,然后我们的当前页面再去得到iframe获取到的数据。

# window.postMessage(message,targetOrigin)

html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。
需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。