zoukankan      html  css  js  c++  java
  • 前端跨域总结

    一、通过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

  • 相关阅读:
    [搬运] Tina R329 swupdate OTA 步骤
    摄像头 ISP 调试的经验之谈(以全志 AW hawkview 为例)
    2021 年了 在 WSL2 中使用 adb 、fastboot 的等命令
    wsl2 编译 linux openwrt 项目的时候,经常会出现 bash: -c: line 0: syntax error near unexpected token `('
    sipeed v833 硬件验证以及开发记录(2021年5月18日)
    Allwinner & Arm 中国 & Sipeed 开源硬件 R329 SDK 上手编译与烧录!
    把 R329 改到 ext4 sdcard 启动变成 Read-Only 系统,导致没有文件修改权限后如何修复。
    linux kernel version magic 不一致导致的模块 加载 (insmod) 不上
    剑指 Offer 17. 打印从1到最大的n位数
    剑指 Offer 16. 数值的整数次方
  • 原文地址:https://www.cnblogs.com/zhaow/p/7874509.html
Copyright © 2011-2022 走看看