跨域与JSONP,CORS

一、同源策略

1.什么是同源

如果两个页面的协议域名端口都相同,则两个页面具有相同的源
类似于怎么知道两个人是不是老乡,相同省?相同市?
怎么知道两个页面来自于同一个地方(同一个源)?判断协议域名端口是否都相同。
端口如果没有指定:xxx,则默认是80

2.什么是同源策略

Same origin policy 是浏览器提供的一个安全功能
它限制了从同一个源加载的文档/脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
通俗理解:浏览器规定,A网站的Javascript,不允许和非同源的网站C之间进行资源的交互,例如:无法读取非同源网页的Cookie,LocalStorage和IndexedDB;无法接触非同源网页的DOM;无法向非同源地址发Ajax请求

二、跨域

1.什么是跨域

同源指的是两个URL的协议,域名,端口一致,反之,这三个中有任何一项/多项不一致,则是跨域
出现跨域的根本原因浏览器的同源策略不允许非同源的URL之间进行资源的交互
例如,网页http://www.test.com/index.html中调用Ajax请求接口:http://www.api.com/userlist中的数据,就会失败。

2.浏览器对跨域请求的拦截

注意:浏览器允许发起跨域请求,但是跨域请求回来的数据会被浏览器拦截,无法被页面获取到!
在这里插入图片描述

3.如何实现跨域数据请求

最主要的两种解决方案,分别是JSONPCORS
JSONP:出现的早,兼容性好,是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持GET请求,不支持POST请求。
CORS:出现的较晚,它是W3C标准,属于跨域Ajax请求的根本解决方案,支持GET和POST请求。缺点是不兼容某些低版本的浏览器。

三、JSONP

JSON with Padding 是JSON的一种"使用模式",可用于解决主流浏览器的跨域数据访问的问题。
概念:浏览器端通过< script >标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做JSONP。

1.JSONP的实现原理

由于浏览器同源策略的限制,网页中无法通过Ajax请求非同源的接口数据。但是< script >标签不受浏览器同源策略的影响,可以通过src属性,请求非同源的js脚本。
因此,JSONP的实现原理,就是通过< script >标签的src属性,请求跨域数据接口,并且通过函数调用的形式,接收跨域接口响应回来的数据。
如果出现跨域问题,会报错:‘Access-Control-Allow-Orign’ header is present on the requested resource
(1)将函数的定义和调用分为两个script标签

    <script>
        var success=function(data){
            console.log('拿到了data数据:')
            console.log(data)
        }
    </script>
    <script>
        success({name:'zs',age:20})
    </script>

(2)将函数的调用抽离为单独的JS文件
在这里插入图片描述

  <script src="./js/1.js"></script>

(3)如果我们调用的是服务器的文件,里面有很多函数,那怎么能执行success这个函数呢?
通过callback指定回掉函数的名称

  <script src="./js/1.js?callback=success"></script>

2.自己实现一个简单的JSONP

    <script>
        var success=function(data){
            console.log('JSONP响应回来的数据是:')
            console.log(data)
        }
    </script>

    <script src="http://...:3006/api/jsonp?callback=success&name=zs&age=20"></script>

3.JSONP的缺点

只能支持GET数据请求,不支持POST请求
注意:JSONP和Ajax之间没有任何关系,不能把JSONP请求数据的方式叫做Ajax,因为JSONP没有用到XMLHttpRequest这个对象。

4.jQuery中的JSONP

jQuery提供的$.ajax()函数,除了可以发起真正的Ajax数据请求之外,还能够发起JSONP数据请求,例如

   $.ajax({
        url:'http://...:3006/api/jsonp?name=zs&age=20',
        dataType:'jsonp',
        success:function(res){
            console.log(res)
        }
    })

默认情况下,使用jQuery发起JSONP请求,会自动携带一个callback-jQueryxxx的参数,jQueryxxx是随机生成的一个回掉函数名称。

5.自定义参数及回调函数名称

callback-jQueryxxx是随机生成的
自定义,需要如下两个参数来指定:jsonp(指定参数,默认是callback),jsonpCallback(指定回调函数名称,默认值是jQueryxxx格式)

   $.ajax({
        url:'http://...:3006/api/jsonp?name=zs&age=20',
        dataType:'jsonp',
        jsonp:'callback',
        jsonpCallback:'abc',
        success:function(res){
            console.log(res)
        }
    })

6.jQuery中的JSONP的实现过程

jQuery中的JSONP也是通过< script >标签的src属性实现跨域数据访问的,只不过,jQuery采用的是动态创建和移除< script >标签的方式,来发起JSONP数据请求。
发起JSONP请求的时候,动态向< header>中append一个< script>标签
JSONP请求成功后,动态从< header>中移除刚才append进去的< script>标签

7.实现JSONP的接口

app.get('/api/jsonp',(req,res)=>{
      // 1. 得到函数的名称
      const funcName=req.query.callback
      // 2. 定义要发送到客户端的数据对象
      const data={name:'zs',age:22}
      // 3. 拼接处一个函数调用
      const scriptStr=`${funcName}(${JSON.stringify(data)})`
      // 4. 把拼接好的字符串,响应给客户端
      res.send(scriptStr)
})

四、CORS跨域资源共享

1.使用cors中间件解 决跨域问题

cors是Express的一个第三方中间件,通过安装和配置cors中间件,可以很方便地解决跨域问题
使用步骤分如下三步:
(1)运行npm install cors安装中间件
(2)使用const cors=require( ’ cors’ )导入中间件
(3)在路由之前调用app.use(cors())配置中间件

2.什么是CORS

Cross-Origin Resource Sharing,跨域资源共享,由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源
浏览器的同源安全策略默认会阻止网页"跨域"获取资源,但如果接口服务器配置了CORS相关HTTP响应头,就可以解除浏览器端的跨域访问限制
在这里插入图片描述

3.CORS的注意事项

(1)CORS主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了CORS的接口
(2)CORS再浏览器中有兼容性。只有支持XMLHttpRequest Level2的浏览器,才能正常访问开启了CORS的服务端接口(例如:IE10+,Chrome4+,FireFox3.5+)

4.CORS响应头部___Access-Control-Allow-Origin

响应头部中可以携带一个Access-Control-Allow-Origin字段,其语法如下:

Access-Control-Allow-Origin: <origin> | *

其中,origin参数的值指定了允许访问该资源的外域URL
例如:下面的字段值将只允许来自http://xxx.cn的请求:

res.setHeader('Access-Control-Allow-Origin','http://xxx.cn')

如果指定了Access-Control-Allow-Origin字段的值为通配符*,表示允许来自任何域的请求,事例代码如下:

res.setHeader('Access-Control-Allow-Origin','*')

5.CORS响应头部___Access-Control-Allow-Headers

默认情况下,CORS支持客户端向服务器发送如下9个请求头:
Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过Access-Control-Allow-Headers对额外的请求头进行声明,否则这次请求会失败!

// 允许客户端额外向服务器发送Content-Type请求头和X-Custom-Header请求头
// 多个请求头之间用英文的,进行分隔
res.setHeader('Access-Control-Allow-Headers','Content-Type,X-Custom-Header')

5.CORS响应头部___Access-Control-Allow-Methods

默认情况下,CORS仅支持客户端发起GET,POST,HEAD请求
如果客户端希望通过PUT,DELETE等方式请求服务器资源,则需要在服务器端,通过Access-Control-Allow-Methods来指明实际请求所允许使用的HTTP方法
事例代码如下:

// 只允许POST,GET,DELETE,HEAD请求方式
res.setHeader('Access-Control-Allow-Methods','POST,GET,DELETE,HEAD')
// 允许所有的HTTP请求方式
res.setHeader('Access-Control-Allow-Methods','*')

6.CORS请求的分类

客户端在请求CORS接口时,根据请求方式和请求头的不同,可以将CORS的请求分为两大类,分别是:
(1)简单请求
同时满足以下两大条件:
请求方式:GET,POST,HEAD三者之一;无定义头部字段
(2)简单请求
什么是预检请求?
在浏览器与服务器正式通信之前,浏览器会先发送OPTION请求进行预检,以获知服务器是否允许该实际请求,所以这一次的OPTION请求称为"预检请求"。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。
只要符合以下任何一个条件的请求,都需要进行预检请求:
请求方式是GET,POST,HEAD之外的请求Method类型;
请求头中包含自定义头部字段;
向服务器发送了application/json格式的 数据
(3)简单请求和简单请求之间的区别
简单请求的特点:客户端与服务器之间只会发生一次请求
预检请求的特点:客户端与服务器之间会发生两次请求,OPTION预检请求成功后,才会发起真正的请求

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值