【Ajax】同源策略、跨域和JSONP

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、同源策略

    • 什么是同源

如果两个页面的协议域名端口都相同则两个页面具有相同的源。

例如下表给出了相对于 http://www.test.com/index.html 页面的同源检测如果没有写端口号默认是80

URL

是否同源

原因

http://www.test.com/other.html

同源协议、域名、端口相同

https://www.test.com/about.html

协议不同http 与 https

http://blog.test.com/movie.html

域名不同www.test.comblog.test.com

http://www.test.com:7001/home.html

端口不同默认的 80 端口与 7001 端口

http://www.test.com:80/main.html

同源协议、域名、端口相同

2. 什么是同源策略

同源策略英文全称 Same origin policy是浏览器提供的一个安全功能

MDN 官方给定的概念同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

通俗的理解浏览器规定A 网站的 JavaScript不允许和非同源的网站 C 之间进行资源的交互例如

  • 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

  • 无法接触非同源网页的 DOM

  • 无法向非同源地址发送 Ajax 请求

二、跨域

1. 什么是跨域

同源指的是两个 URL 的协议、域名、端口一致反之如果两个 URL 的协议、域名、端口中有一项或多项不一致则是跨域

出现跨域的根本原因浏览器的同源策略不允许非同源的 URL 之间进行资源的交互。

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

注意浏览器允许发起跨域请求服务器也可以接收到跨域请求但是跨域请求回来的数据会先被浏览器的同源策略拦截无法被页面获取到数据也就无法传给ajax

  <script src="./lib/jquery.js"></script>

  // 发起跨域的AJAX请求
  <script>
    $.ajax({
      method: 'GET',
      url: 'http://ajax.frontend.itheima.net:3006/api/jsonp',
      data: {
        name: 'zs',
        age: 20
      },
      success: function (res) {
        console.log(res)
      }
    })  
  </script>

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

现如今实现跨域数据请求最主要的两种解决方案分别是 JSONP 和 CORS。

JSONP出现的早兼容性好兼容低版本IE。是前端程序员为了解决跨域问题被迫想出来的一种临时解决方案。缺点是只支持 GET 请求不支持 POST 请求

CORS出现的较晚它是 W3C 标准属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。

三、JSONP

    • 什么是JSONP

JSONP (JSON with Padding) 是 JSON 的一种“使用模式”可用于解决主流浏览器的跨域数据访问的问题。

2. JSONP的实现原理

由于浏览器同源策略的限制网页中无法通过 Ajax 请求非同源的接口数据。但是 <script> 标签不受浏览器同源策略的影响可以通过 src 属性请求非同源的 js 脚本

因此JSONP 的实现原理就是通过 <script> 标签的 src 属性请求跨域的数据接口并通过函数调用的形式接收跨域接口响应回来的数据。

  <script>
    // 定义一个 success 回调函数
    function success(data) {
      console.log('拿到了Data数据')
      console.log(data)
    }
  </script>

  <!-- 通过 <script> 标签请求接口数据 -->
  <script src="./js/getdata.js?callback=success"></script>
  <!-- src请求外部的js文件 -->
  <!-- 希望能返回函数的调用调用success() -->

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

  <script>
    // 1. 定义回调函数
    function abc(data) {
      console.log('JSONP响应回来的数据是')
      console.log(data)
    }
  </script>

<!-- 通过 <script> 标签的src属性请求接口数据 -->
  <script src="http://www.liulongbin.top:3006/api/jsonp?callback=abc&name=ls&age=30">
  </script>

4. JSONP的缺点

由于 JSONP 是通过 <script> 标签的 src 属性来实现跨域数据获取的所以JSONP 只支持 GET 数据请求不支持 POST 请求。

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

5. jQuery中的JSONP

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

  <script>
    $(function () {
      // 发起JSONP的请求
      $.ajax({
        url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
        // 如果要使用 $.ajax() 发起 JSONP 请求必须指定 datatype 为 jsonp
        dataType: 'jsonp',
        success: function (res) {
          console.log(res)
        }
      })
    })
  </script>

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

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

在使用 jQuery 发起 JSONP 请求时如果想要自定义 JSONP 的参数以及回调函数名称可以通过如下两个参数来指定

// 发送到服务端的参数名称默认值为 callback
jsonp: 'callback',
// 自定义的回调函数名称默认值为 jQueryxxx 格式
jsonpCallback: 'abc',
  <script>
    $(function () {
      // 发起JSONP的请求
      $.ajax({
        url: 'http://www.liulongbin.top:3006/api/jsonp?name=zs&age=20',
        // 如果要使用 $.ajax() 发起 JSONP 请求必须指定 datatype 为 jsonp
        dataType: 'jsonp',

        // 自定义参数及回调函数名称
        // 发送到服务端的参数名称默认值为 callback
        jsonp: 'callback',
        // 自定义的回调函数名称默认值为 jQueryxxx 格式
        jsonpCallback: 'abc',

        success: function (res) {
          console.log(res)
        }
      })
    })
  </script>

7. jQuery中JSONP的实现过程

jQuery 中的 JSONP也是通过 <script> 标签的 src 属性实现跨域数据访问的只不过jQuery 采用的是动态创建和移除 <script> 标签的方式来发起 JSONP 数据请求

  • 在发起 JSONP 请求的时候动态向 <header> 中 append 一个 <script> 标签

  • 在 JSONP 请求成功以后动态从 <header> 中移除刚才 append 进去的 <script> 标签。

  <script src="./lib/jquery.js"></script>

  <button id="btnJSONP">发起JSONP数据请求</button>

  <script>
    $(function () {
      $('#btnJSONP').on('click', function () {
        $.ajax({
          url: 'http://www.liulongbin.top:3006/api/jsonp?address=北京&location=顺义',
          dataType: 'jsonp',
          jsonpCallback: 'abc',
          success: function (res) {
            console.log(res)
          }
        })
      })
    })
  </script>

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6