前端跨域总结

一、通过document.domain + iframe实现
二、通过location.hash + iframe实现
三、通过window.name + iframe实现
四、通过HTML5的postMessage方法实现
上面三种方法都属于破解,HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。
这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。

举例来说,父窗口http://aaa.com向子窗口http://bbb.com发消息,调用postMessage方法就可以了。

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');

 postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。
子窗口向父窗口发送消息的写法类似。

window.opener.postMessage('Nice to see you', 'http://aaa.com');

 父窗口和子窗口都可以通过message事件,监听对方的消息。

window.addEventListener('message', function(e) {
  console.log(e.data);
},false);

message事件的事件对象event,提供以下三个属性。
event.source:发送消息的窗口
event.origin: 消息发向的网址
event.data: 消息内容

下面的例子是,子窗口通过event.source属性引用父窗口,然后发送消息。

window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
  event.source.postMessage('Nice to see you!', '*');
}

event.origin属性可以过滤不是发给本窗口的消息。

window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
  if (event.origin !== 'http://aaa.com') return;
  if (event.data === 'Hello World') {
      event.source.postMessage('Hello', event.origin);
  } else {
    console.log(event.data);
  }
}

更多内容:http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

五、通过jsonp实现
用JSONP获取的不是JSON数据,而是可以直接运行的JavaScript语句。
示例代码:
站点1,用来跨域请求的目标地址:http://localhost:8098/index.aspx
index.aspx.cs处理逻辑实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace JSONPTest1
{
    public partial class index : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //模拟数据
            string jsonData="{"IsSuccess":true,"Message":"承保成功","result":{"TransRefGUID":"YSYJY201711211118578452","Code":"22201711211106260661645","Id":"368"}}";
            string callBack = Request.QueryString["callback"];
            Response.Write(callBack + "(" + jsonData + ")");
            Response.End();
        }
    }
}

站点2,发送跨域请求的地址:http://localhost:8199/index.aspx
这个页面中,有三种方式实现跨域访问:
1、通过script标签指向

<script type="text/javascript">
	//通过script标签指向跨域地址时,需要执行的回调函数
	function callbackProcess(data) {
		alert(JSON.stringify(data));
	}
</script>
<!--通过script标签指向实现-->
<script type="text/javascript" src="http://localhost:8098/index.aspx?callback=callbackProcess"></script>

2、通过jQuery的$.ajax方法

<script src="Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
	//通过jQuery的全局方法$.ajax实现
	var url = "http://localhost:8098/index.aspx";
	$.ajax({
		url: url,
		//这里虽设置为POST,但其实还是走的GET方式,
		//因为要请求的页面是用Request.QueryString["callback"]来接收参数的,如果POST有效的话,那请求就会报错了,
		//所以,正常执行就说明其实走的是GET。
		type: "POST",
		dataType: "jsonp",
		//告诉服务器通过什么字段获取回调函数的名称
		//如果设置的值与跨域请求的目标要接收的参数值不一致,则会报错,执行error
		jsonp: "callback",
		//声明本地回调函数的名称
		jsonpCallback: "callbackProcess",
		success: function (data) {
			alert("ajax success callback: " + JSON.stringify(data))
		},
		error: function (jqXHR, textStatus, errorThrown) {
			alert(textStatus + ' ' + errorThrown);
		}
	})
</script>

3、通过jQuery的getJSON方法

<script src="Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
	//通过jQuery的getJSON方法实现
	var url = "http://localhost:8098/index.aspx";
	$.getJSON(url+"?callback=?", {}, function (data,textStatus,jqXHR) {
		alert("data:" +JSON.stringify(data) + "
textStatus:" + textStatus);
	})
</script>

以上三种方式执行的结果大致是这样的:

jsonp缺点:
1、只能使用 GET 方法发起请求,这是由于 script 标签自身的限制决定的。
2、不能很好的发现错误,并进行处理。与 Ajax 对比,由于不是通过 XmlHttpRequest 进行传输,所以不能注册 success、 error 等事件监听函数。
(这点只针对第1种方式,2、3种可以监听success、 error)

六、通过CORS实现
CORS(Cross-Origin Resource Sharing)跨域资源共享。
IE10+
实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
更多内容:http://www.cnblogs.com/zhaow/articles/9056089.html
CORS和JSONP对比
1、JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。
4、CORS与JSONP相比,无疑更为先进、方便和可靠。

七、 nginx代理跨域
八、 nodejs中间件代理跨域
九、 WebSocket协议跨域

参考资料:
http://www.ruanyifeng.com/blog/2016/04/cors.html
https://mp.weixin.qq.com/s/NOmsbKZsryTUONQj2gBFIA
http://mp.weixin.qq.com/s/CZgz0ya_RXhzDkEfv2_9iw
https://funteas.com/topic/59f6f16dadc582cf09ba794f
http://mp.weixin.qq.com/s/nZ26szrbNVQMwAo0rl3U9g
http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

原文地址:https://www.cnblogs.com/zhaow/p/7874509.html