跨域的7种方式

JSONP(json with padding)是一种借助script元素实现跨域的技术,它不会使用XHR对象。
script 元素有以下两个特点
1.它的src属性能够访问任何URL资源,不会受同源策略的限制。
2.如果访问的资源包含js代码,那么在下载完成后会自动执行。
JSONP就是基于这两点,再与服务器配合来实现跨域请求的
1.定义一个回调函数
2.用DOM方法动态创建一个script元素。
3.指定要请求的URL,并且将回调函数的名称作为一个参数传递过去。
4.将script元素插入到当前文档中,请求开始。
5.服务器接收传递过来的参数,然后将回调函数和数据以调用的形式输出。
6.当script元素接收到响应中的脚本代码后,就会自动执行它们。
前四步

function handle()
{
    console.log("回调函数");
}
var script = document.createElement("script");
script.src = "jsonp.php?jponp=handle"; //传递回调函数的名称
document.body.appendChild(script);

第五步

<?php
    $func = $_GET['jsonp'];
    $json = [
    'code' => '200',
    'msg'  => '操作成功',
    'data' => ['prev'=>'2016-09','next'=>'2016-11',]
            ];
    echo $func.'('.json_encode($json).')';
>

优点:

它不像XMLHttpRequest 对象实现 Ajax 请求那样受到同源策略的限制
兼容性很好,在古老的浏览器也能很好的运行
不需要 XMLHttpRequest 或 ActiveX 的支持;并且在请求完毕后可以通过调用 callback 的方式回传结果。

缺点:

它支持 GET 请求而不支持 POST 等其它类行的 HTTP 请求。
它只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面或 iframe 之间进行数据通信的问题
无法捕获 Jsonp 请求时的连接异常,只能通过超时进行处理

● 知道什么跨域方式吗,jsonp具体流程是什么,如何实现原生Jsonp封装,优化,对于CORS,服务器怎么判断它该不该跨域呢

常见的跨域方式大概有七种,大致可分为iframe、api跨域
1、JSONP,全称为json with padding,解决老版本浏览器跨域数据访问问题,原理是web页面调用JS文件不受浏览器同源策略限制,所以通过script标签可以进行跨域请求,流程如下:

首先前端设置好回调参数,并将其作为URL的参数

服务器端收到请求后,通过该参数获取到回调函数名,并将数据放在参数中返回

收到结果后因为是script标签,所以浏览器当做脚本运行,

2、cors,全称是跨域资源共享,允许浏览器向跨源服务器发出XMLHTTP Request请求,从而克服了ajax只能同源使用的策略,实现cors的关键是服务器,只要服务器实现了cros接口,就可以跨域通信

前端逻辑很简单,正常发起ajax请求即可,成功的关键在于服务器 Access-Control-Allow-Origin 是否包含请求页面的域名,如果不包含的话,浏览器将认为这是一次失败的异步请求,将会调用 xhr.onerror 中的函数。

Cros使用简单,支持POST方式,但是存在兼容问题

浏览器将cors请求分为两类,简单请求和非简单请求,对于简单请求,浏览器直接发出cors请求,就是在头信息之中增加一个origin字段,用于说明本次请求来自哪个协议+域名+端口,服务器根据这个值,决定是否同意本次请求,如果服务器同意本次请求,返回的响应中会多出几个头信息字段:

Access-Control-Allow-Orign:返回origin的字段或者*

Access-Control-Allow-Credentials,该字段可选,是一个bool值,表示是否允许发送cookie,

Access-Control-Expose-Headers

该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值

非简单请求

第一步 预检请求的头信息字段

Access-Control-Request-Method
该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法

Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段

第二步 预检请求的回应
服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

(1)Access-Control-Allow-Methods

该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

(2)Access-Control-Allow-Headers

如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

(3)Access-Control-Allow-Credentials

该字段与简单请求时的含义相同。

(4)Access-Control-Max-Age

该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

CORS 的优缺点:
使用简单方便,更为安全
支持 POST 请求方式
CORS 是一种新型的跨域问题的解决方案,存在兼容问题,仅支持 IE 10 以上

参考:CORS

3、服务器代理:

即当你有跨域的请求操作时发给后端,让后端帮你代为请求.

此外还有四中不常用的方式,也可了解下:

location.hash

在 url 中,http://www.baidu.com#helloworld 的 “#helloworld” 就是 location.hash,改变 hash 值不会导致页面刷新,所以可以利用 hash 值来进行数据的传递,当然数据量是有限的,并且数据直接暴露在了 url 中。
iframe设置为要跨域的页面,然后收到消息后来修改hash值达到数据传递的效果

Window.name
window.name(一般在 js 代码里出现)的值不是一个普通的全局变量,而是当前窗口的名字,这里要注意的是每个 iframe 都有包裹它的 window,而这个 window 是 top window 的子窗口,而它自然也有 window.name 的属性,window.name 属性的神奇之处在于 name 值在不同的页面(甚至不同域名)加载后依旧存在(如果没修改则值不会变化),并且可以支持非常长的 name 值(2MB)。

window.name = "Hello World"
window.location = "http://www.baidu.com"

设置window.name 然后跳转页面,window.name的值依然存在
通过iframe 然后把传递来的数据保存在window.name里面

postMessage
postMessage 是 HTML5 新增加的一项功能,跨文档消息传输(Cross Document Messaging)
创建一个 iframe,使用 iframe 的一个方法 postMessage 可以想 http://localhost:8081/data.html 发送消息,然后监听 message,可以获得其文档发来的消息。
跨域页面也通过postmessage发送消息,然后源页面通过监听onmessage事件来获取数据

document.domain
对于主域相同而子域不同的情况下,可以通过设置 document.domain 的办法来解决,具体做法是可以在 http://www.example.com/index.html 和 http://sub.example.com/data.html 两个文件分别加上 document.domain = “example.com” 然后通过 index.html 文件创建一个 iframe,去控制 iframe 的 window,从而进行交互,当然这种方法只能解决主域相同而二级域名不同的情况

参考:https://juejin.im/entry/59feae9df265da43094488f6

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值