记录-跨域的形成和跨域方法

2023-11-01

1,什么是跨域

根据浏览器的同源策略,凡是发送请求Url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。

同源策略:同域名(domain或IP),同端口,同协议视为同一个域,一个域内的脚本仅仅具有本域内    的权限,可以理解为本域脚本只能读写本域内的资源,而无法访问其它域的资源。这种安全限制称为同源策略。也是浏览器最核心也最基本的安全功能。

存在跨域的情况:

  1. 网络协议不同,如http协议访问https协议。
  2. 端口不同,如80端口访问8080端口。
  3. 域名不同,如blog.com访问baidu.com。
  4. 子域名不同,如a.blog.com访问b.blog.com。
  5. 域名和域名对应的IP,如www.a.com访问20.205.28.90

2,跨域的方法
2.1JSON

2.1.1,jsonp的定义

    jsonp全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议。

    json是描述信息的格式,jsonp是信息传递双方约定的方法。

2.1.2,jsonp的产生:

  1. ajax直接请求普通文件存在跨域无权限访问的问题,不管是静态页面也好。
  2. 我们在调用js文件的时候又不受跨域影响。
  3. 凡是拥有src这个属性的标签都可以跨域,<scripte><img><iframe>
  4. 如果想通过纯web端跨域访问数据只有一种可能,那就是把远程服务器上的数据装进js格式的文件里。
  5. 而json又是一个轻量级的数据格式,被js原生支持。
  6. 为了便于客户端使用数据,逐渐形成了一种非正式的传输协议,人们称为jsonp。该协议的一个要点就是允许用户传递一个callback参数给服务器。
  7. script标签是不受同源策略影响的,可以引入来自任何地方的js文件。

2.1.3,jsonp的实现:

jsonp是借助了script标签节点跨域访问/获取的特性

jsonp实现跨域请求的原理简单来说,就是动态创建<script>标签,然后利用<script>的src不受同源策略约束来跨域获取数据。

jsonp有两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据。(客户端将创建带有回调函数名的script标签,指定Url,发送请求,响应时,服务端会调用该回调函数名的回调函数,然后data,就是json数据,返回给客户端。)

(1)客户端(a)的HTML文件(简单的):

<script>
function jsonpCallBack(data){
   console.log(data);
}
</script>
<script type="text/javascript" src="http://a?callback=jsonpCallBack"></script>

(2)客户端(a)的HTML文件(复杂的):

<script>
  function jsonpCallBack(data){
    console.log(data);
  }
var jsonp = document.createElement("script");
jsonp.type="text/javascript";
jsonp.src="http://a?callback=jsonpCallBack";
document.getElementsByTagName("head")[0].appendChild(jsonp);
</script>

可以将该方法抽象为一个函数,进行调用:

function jsonp(){
var jsonp=document.createElement("script");
jsonp.type="text/javascript";
jsonp.src="http://a?callback=jsonpCallBack";
document.getElementsByTagName("head")[0].appendChild(jsonp);
}
jsonp();

(3)服务器(b)的php代码:

<?php    
    //服务端返回JSON数据  
    //$arr=array('a'=>1,'b'=>2,'c'=>3); 
    $arr->IsLatestVersion = False;
    $arr->version = ‘3.3.2.764’;
    $arr->url = "http://b/c.exe"; 
    $result=json_encode($arr);  
    //动态执行回调函数  
    $callback=$_GET['callback'];  
    echo $callback."($result)";  
?>

这样jsonp的原理就很清楚了,首先在客户端注册一个callback,然后动态创建script标签通过src引入服务器端的php文件(类似于引入js文件的方式),同时将客户端注册的callback的名字传递给服务器,php载入之后,服务器先生成我们需要的json数据,然后将其作为参数传入我们在Url参数中指定的函数,所以jsonp是需要服务器端的页面进行相应的配合的。


2.1.4,jQuery实现jsonp

jsonp的方式只是针对get请求方法,不支持post请求。jsonp的局限性。

jquery本身支持jsonp,jquery封装在$.ajax中的一个dataType属性,将该属性设置为dataType:"jsonp",就可以指定按照jsonp的方式访问远程服务实现跨域。

$(document).ready(function(){
    $.ajax({
        url: "http://b/c.php",
        type: "GET",
        dataType: "jsonp",
        jsonp: "callback",
        jsonpCallback: "myCallback",
        async: false,
        data: {
            'version': "3.2.3.660",
            'os': "Windows",
        },        
        timeout:3000,        
        success: function(result) {
            console.log(result);
            for(var i in result) {  
                console.log(i+":"+result[i]); 
            }
        },
        error: function(xhr) {
            console.log(xhr);
        },            
    });
});

之后继续补充jsonp。

2.2Img

Img标签也是没有跨域限制的,但它只能用来发送GET请求,且无法获取服务端的响应文本,可以利用它实现一些简单的、单向的跨域通信,用来追踪用户点击:

var img=new Image();
img.src='http://a';
img.οnerrοr=function(){
 alert('error');
}
img.οnlοad=function(){
 alert('success');
}

2.3,window.name

window对象拥有name属性,name有一个特点:在相同协议下,在一个页面内,不随Url的改变而改变。

window.name = 'string' // 字符串,一般允许的最大值为2M
console.log(window.name)  //string
location = 'http://baidu.com/'

window.name的值只能是字符串,其他类型会转化为string。

window.name = function(){}
console.log(window.name);//“function(){}”

通过window.name实现跨域,iframe拥有contentWindow属性,其指向该iframe的window对象的引用(相当于iframe加载的window对象),如果在iframe的src指向的页面中设置window.name值,那么就可以通过iframe.contentWindow.name就可以取到这个值。

var url = "http://a.com/windowName";
var iframe = document.createElement('iframe')
iframe.onload = function(){
    var data = iframe.contentWindow.name
    console.log(data)
}
iframe.src = url
document.body.appendChild(iframe)

然而,chrome提示你跨域了。

因为不同源,当前页面是无法取到iframe.contentWindow.name,需要把iframe.src改成同源。

var url = "http://a/windowName";
var iframe = document.createElement('iframe')
iframe.onload = function(){
    iframe.src = 'favicon.ico';
    var data = iframe.contentWindow.name
    console.log(data)
}
iframe.src = url
document.body.appendChild(iframe)

刷新页面,会发现iframe不断的刷新,因为每次的onload,iframe的src被修改,就触发onload,就会陷入循环。进行修改,和封装。

   <script type="text/javascript">
    function domainData(url, fn)
    {
        var isFirst = true;   //一种状态
        var iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        var loadfn = function(){
            if(isFirst){
                iframe.contentWindow.location = 'http://a.com/null.html';    //加载同源内的页面,可以是空
                isFirst = false;
            } else {
                fn(iframe.contentWindow.name);         //回调函数
                iframe.contentWindow.document.write('');
                iframe.contentWindow.close();    //关闭iframe
                document.body.removeChild(iframe);
                iframe.src = '';
                iframe = null;
            }
        };
        iframe.src = url;      //修改src的值,不同域的Url
        if(iframe.attachEvent){
            iframe.attachEvent('onload', loadfn);   //函数在body后发生
        } else {
            iframe.onload = loadfn;
        }
         
        document.body.appendChild(iframe);
    }
    </script>
    <script type="text/javascript">
    domainData('http://b.com/data.html', function(data){
        alert(data);
    });
    </script>
理解:利用window.name来跨域,就是借用iframe的跨域。知道window.name不轻易改变的情况下,通过iframe.contentWindow.name来取到window.name的值,相当于,打开一扇任意门,门在出现的情况下(iframe创建),门后通向哪里,是有我们想去哪里决定的(不同源的Url)。这也是为什么需要一个同源的null.html。我们没有办法直接从a到b,但是可以通过中间者,iframe建立起a和b之间的联系(理解为门),src可以实现跨域,a通过null.html,有访问权限的情况下(有钥匙打开门),再次改变src的值(门后的通向),就可以访问(到达)b。

2.4,postMessage

postMessage是HTML5新增的一个解决跨域的一个方法,不过ie6,7不支持。

postMessage()允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档,多窗口,跨域消息传递。

otherWindow.postMessage(message, targetOrigin, [transfer]);

  1. otherWindow:其他窗口的引用,iframe的contentWindow属性,window.open等。
  2. message:发送到其他window的数据,字符串。
  3. targetOrigin:指定哪些窗口能接收到消息,字符串或URI。协议+主机号+端口。如果设置为“*”,则表示可以传递给任意窗口。
  4. transfer:和message同时传递的transferable对象,对象的所有权转移给接收方,发送方不再保有所有权。
//假设在http://127.0.0.1:80下
var iframe = document.createElement('iframe')
iframe.onload = function(){
    var popup = iframe.contentWindow
    popup.postMessage("hello", "http://127.0.0.1:5000");
}
iframe.src = 'http://127.0.0.1:5000/lab/postMessage'
document.body.appendChild(iframe)

在另一个窗口接受:

// 监听返回的postMessage
window.addEventListener("message", function(event){
    if (event.origin !== "http://127.0.0.1:5000") return;
    console.log(event.data)
}, false)

可以对数据进行操作:

// 在http://127.0.0.1:5000/lab/postMessage下
window.addEventListener("message", function(event){
    // 验证消息来源
    if (event.origin !== "http://127.0.0.1") return;
    console.log(event.source); // 消息源 popup
    console.log(event.origin); // 消息源URI 
    console.log(event.data); // 来自消息源的数据 
    // 返回数据
    var message = 'world';
    event.source.postMessage(message, event.origin);
}, false);

返回的event属性:

  1. data:数据
  2. origin:postMessage发送消息的origin
  3. source:发送消息窗口的引用,可以用此来在不同的origin的两个窗口之间建立双向通信。

理解:postMessage允许引用的窗口(如iframe),向指定的源进行有限的通讯,origin由“协议+主机号+端口”组成,然后将窗口的src指向想访问的地址(iframe.src),这个地址在源的范围内,这样可以发送信息;另一端,需要有window.addEventListener("message",fn);来监听postMessage事件。

2.5,CORS(Cross-Origin Resource Sharing)

CORS(跨域资源共享)是一种跨域访问的机制,可以让ajax实现跨域访问。它允许一个域上的脚本向另一个域提交跨域ajax请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

Access-Control-Allow-Origin: * // 允许来自任何域的请求
Access-Control-Allow-Origin: http://funteas.com/ // 仅允许来自http://funteas.com/的请求

当客户端的ajax请求的Url为其他域时,对于支持CORS的浏览器,请求头会自动添加Origin,值为当前的host。

var xhr = new XMLHttpRequest();
var url = 'http://bar.other/resources/public-data/';
xhr.open('GET', url, true);
xhr.send();

CORS默认不发送cookie,如果需要发送cookie,需要设置withCredentials

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

同时,服务器也要设置。

Access-Control-Allow-Credentials: true

CORS不是很理解,之后补充吧。


更加详细的跨域方案: 9种方案

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

记录-跨域的形成和跨域方法 的相关文章

  • HTTP协议/RTP/RTSP协议/RTMP协议的区别

    RTSP RTMP HTTP的共同点 区别 共同点 1 RTSP RTMP HTTP都是在应用应用层 2 理论上RTSP RTMPHTTP都可以做直播和点播 但一般做直播用RTSP RTMP 做点播用HTTP 做视频会议的时候原来用SIP协

随机推荐

  • react与antd搭配实现图片上传与设置主图功能

    antd的upload可以实现上传 但是其上传之后 图片列表展示都是其组件里面已经封装好的 也没有vue那种提供插槽solt的功能 但是我司需要实现在每张图片下方有个radio标签来设置主图 左思右想 是不是得直接把upload组件拿过来再
  • jquery 表单清空

    frm form clear
  • 怎么升级服务器浏览网页速度快,如何快速提升网页速度有哪些优化技巧

    我们使用电脑和手机时候最不能忍受就是设备又卡又慢了 严重影响我们工作或者游戏体验 对于网页打开速度优化 肯定会说到SEO规则 下面一起看看具体分析 一 谷歌如何看待网页速度 首先我们以谷歌为例 了解搜索引擎是如何看待这个问题 早前 谷歌的资
  • 华为OD机试真题-统计友好度最大值【2023Q1】

    题目描述 工位由序列F1 F2 Fn组成 Fi值为0 1或2 其中0代表空置 1代表有人 2代表障碍物 1 某一空位的友好度为左右连续老员工数之和 2 为方便新员工学习求助 优先安排友好度高的空位 给出工位序列 求所有空位中友好度的最大值
  • UE4文件读写(.txt文本文档)

    UE4文件读写 txt文本文档 一 创建C 类继承BlueprintFunctionLibrary 二 用到的函数 读取文件 bool FFileHelper LoadFileToString FString Result const TC
  • node.js os模块

    获取 系统信息的模块 包括操作系统和硬件信息 但是能力很有限 用法 var os require os node版本 0 8 22 os tmpdir 获取系统的临时目录 os endianness 获取cpu的字节序 返回的值可能是 BE
  • HBase的数据热点和Hbase常见避免热点问题的方法

    只要使用过 听说过HBase的人 我想对HBase的数据热点想必也不会陌生 数据热点是如何出现的 这得从HBase的存储结构说起 对于HBase详细的存储结构可以上网搜一下 这里就不补充了 我们只需要知道 我们的HBase的表会被划分为1个
  • 【模型部署】c++调用tensorRT的模型(engine)

    将分割模型就行腾搜人RT转化后得到engine 该博客主要是针对c 调用tensorRT的模型文件engine 文章目录 1 框架 2 main tensorRT exe 2 1 LoadCathodeHeadEngine 读取模型 2 2
  • odoo报错:AttributeError: ‘_unknown‘ object has no attribute ‘id‘

    在开发中遇到的这个问题 AttributeError unknown object has no attribute id 1 当在一个模块中写了一个many2one字段 例如a fields many2one base repair 基础
  • TTL电平和CMOS电平总结

    转载自 https blog csdn net godloveyuxu article details 72965351 1 TTL电平 输出高电平 gt 2 4V 输出低电平 lt 0 4V 在室温下 一般输出高电平是3 5V 输出低电平
  • R数据科学-第4章使用tibble实现简单数据框

    下面一个部分将介绍数据处理 将数据以合适的形式导入R 从而进行可视化和建模 tibble是一种简单数据框 其更易于在tidyverse中使用 一 使用与创建 1 将数据框转换为tibble gt library tidyverse gt a
  • SpringBoot2.x 集成Activiti6.xs :java.lang.ArrayStoreException: sun.reflect.annotation.***

    今天使用SpringBoot2 x 版本集成Activiti 6 x 启动Application java 程序 提示如下错误信息 org springframework beans factory BeanCreationExceptio
  • css隐藏状态,仅使用CSS淡出后隐藏元素

    CSS page moz animation name fadeIn webkit animation name fadeIn ms animation name fadeIn animation name fadeIn moz anima
  • IDEA-使用插件远程连接Redis(收费与免费插件)

    前言 IDEA连接Redis可视化 可以在IDEA中 删除存储的缓存等操作 使用 1 收费 点击工具栏的File gt Settings gt Plugins 然后进行搜索Redis 我这里下载过了 然后点击Install进行下载 下载好后
  • 《推荐系统实践》第二章 利用用户行为数据

    2 1 用户行为数据简介 在电子商务网站中行为主要包括网页浏览 购买 点击 评分和评论等 用户行为在个性化推荐系统中一般分两种 显性反馈行为 explicit feedback 和隐性反馈行为 implicit feedback 显性反馈行
  • ajax的responseText是什么东西

    你向ajax后台的程序发送xmlhttp请求的时候 后台程序接到请求会进行处理 处理结束后 可以返回一串数据给前台 这个就是responseText 一般在后台程序C 中是Response Write 字符串 php中使用的是echo 就是
  • JVM系列之类加载

    前言 虚拟机把描述类的数据从Class文件加载到内存 并对数据进行校验 转换解析和初始化 最终形成可以被虚拟机直接使用的Java类型 这个过程就称为JVM的类加载机制 今天我们主要从下面两个方面说下类加载 类加载时机和类加载过程 类加载时机
  • 单元测试打桩,通俗易懂解释。

    在软件开发中的单元测试过程中 单元测试打桩通常是一种模拟或替代正在被测试的组件或系统的策略 在单元测试打桩过程中 测试代码使用一个 虚拟 实现来替代掉实际组件或系统的某些部分 从而可以进行封闭式的测试 简单来说 单元测试打桩是一种 模拟卡
  • esp8266&点灯科技&arduino

    ESP8266 点灯科技 arduino esp8266实现温度传感器 利用超声波传感器测距与舵机控制 ESP8266驱动DS18B20 ESP8266与DS18B20的硬件连接 DS18B20引脚排列 3 读取一次DS18B20温度数据
  • 记录-跨域的形成和跨域方法

    1 什么是跨域 根据浏览器的同源策略 凡是发送请求Url的协议 域名 端口三者之间任意一与当前页面地址不同即为跨域 同源策略 同域名 domain或IP 同端口 同协议视为同一个域 一个域内的脚本仅仅具有本域内 的权限 可以理解为本域脚本只