Blog
首页
文档
收藏
关于
  • 在线转换时间戳 (opens new window)
  • 在线压缩图片 (opens new window)
  • Float-Double转二进制 (opens new window)
  • 文件转Hex字符串 (opens new window)

HiuZing

🍑
首页
文档
收藏
关于
  • 在线转换时间戳 (opens new window)
  • 在线压缩图片 (opens new window)
  • Float-Double转二进制 (opens new window)
  • 文件转Hex字符串 (opens new window)
  • 前端面试题

    • Vue

    • 计算机网络

      • 浏览器跨域
        • 屏蔽事件
      • CSS

      • JavaScript

      • 小程序

      • 面试记录

    • JavaScript

    • Vue2

    • port

    • CSS

    • Node.js

    • JavaScript优化

    • uniapp

    • Mini Program

    • TypeScript

    • 面向对象编程

    • UI组件

    • Plugin

    • Vue3

    • 性能优化

    • Axios

    • 状态管理

    • React

    • Mock

    • Icon

    • Template

    • 构建工具

    • 项目规范配置

    • Taro

    • SVG

    • React Native

    • 前端
    • 前端面试题
    • 计算机网络
    HiuZing
    2022-03-15
    目录

    浏览器跨域

    # 浏览器跨域

    # 同源策略

    同源:协议、域名、端口号 必须完全相同

    同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据

    违背同源策略就是跨域

    # 跨域

    跨域是指浏览器页面访问不同源的服务器的时候,因为同源策略限制导致的请求不成功

    如果协议、域名或者端口有一个不同,都被当作是不同的域,就不能使用 Ajax 向不同源的服务器发送 HTTP 请求

    请求跨域了,请求到底发出去没有?肯定发出去了,但是浏览器拦截了响应

    # 跨域的解决方式

    1. JSONP(此方法需要前后端配合完成)

      原因:script标签不受同源策略的影响(src 属性没有跨域的限制)

      用法:前端准备好回调函数,放入script标签中的src属性中,向后端发送请求的时候后端就能够拿到

      回调函数,将数据最为参数传给回调函数,前端就可以收到数据

      缺点:只支持get请求,不支持post请求,因为发送的请求携带在script的url中,不带请求体

      //定义获取数据的回调方法
      function getData(data) {
        console.log(data);
      }
      
      // 创建一个script标签,并且告诉后端回调函数名叫 getData
      var body = document.getElementsByTagName('body')[0];
      var script = document.gerElement('script');
      script.type = 'text/javasctipt';
      script.src = 'demo.js?callback=getData';
      body.appendChild(script);
      
      //script 加载完毕之后从页面中删除,否则每次点击生成许多script标签
      script.onload = function () {
        document.body.removeChild(script);
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
    2. cors跨域请求

      用法:首先浏览器会判断该请求是简单请求simple request还是复杂请求not-so-simple request

      • 简单请求

        1.使用GET、POST、HEAD

        2.HTTP的头信息不超出以下几种字段:

        • Accept
        • Accept-Language
        • Content-Language
        • Last-Event-ID
        • Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain

        如果是简单请求会自动在请求头中加上origin(值为浏览器url),后端收到请求后虚打开cors接口:设置access-control-allow-origin的值为前端传过来的origin

        对于简单请求,浏览器直接发起 CORS 请求,具体来说就是服务器端会根据请求头信息中的 origin 字段(包括了协议 + 域名 + 端口),来决定是否同意这次请求

        如果 origin 指定的源在许可范围内,服务器返回的响应,会多出几个头信息字段:

        Access-Control-Allow-Origin: http://xxx.xxx.com
        Access-Control-Allow-Credentials: true
        Access-Control-Expose-Headers: FooBar
        Content-Type: text/html; charset=utf-8
        
        1
        2
        3
        4
      • 复杂请求

        如果非简单请求(put,delete,axios请求等),浏览器会先发送一条预检option请求,预检请求会询问服务器是否支持当前域名的请求,是否支持修改的头信息字段,收到肯定回复后,浏览器才发送真正的http请求,否则报错

        一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样了

        下面是一个预检请求的头部:

        OPTIONS /cors HTTP/1.1
        Origin: http://api.bob.com
        Access-Control-Request-Method: PUT
        Access-Control-Request-Headers: X-Custom-Header
        Host: api.alice.com
        Accept-Language: en-US
        Connection: keep-alive
        User-Agent: Mozilla/5.0...
        
        1
        2
        3
        4
        5
        6
        7
        8
    3. 服务器代理

      浏览器有跨域限制,但是服务器不存在跨域问题,所以可以由服务器请求所要域的资源再返回给客户端

      一般我们在本地环境开发时,就是使用 webpack-dev-server 在本地开启一个服务进行代理访问的

      A要访问C,两者不同源,则A先去访问和A同源的代理服务器B,由于服务器之间不存在跨域,由B去获得C的API接口,返回给A

    4. window提供的可跨域方法postMessage

      window.postMessage 是一个 HTML5 的 api,允许两个窗口之间进行跨域发送消息

      这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息

      // 发送消息端
      var receiver = document.getElementById('receiver').contentWindow;
      var btn = document.getElementById('send');
      btn.addEventListener('click', function (e) {
          e.preventDefault();
          var val = document.getElementById('text').value;
          receiver.postMessage("Hello "+val+"!", "http://res.42du.cn");
      }); 
      
      // 接收消息端
      window.addEventListener("message", receiveMessage, false);
      function receiveMessage(event){
        if (event.origin !== "http://www.42du.cn")
          return;
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
    5. document.domain(iframe跨域问题)

      该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式

      只需要给两个页面都添加 document.domain = 'test.com',通过在 a.test.com 创建一个 iframe,去控制 iframe 的 window,从而进行交互

    #跨域
    上次更新: 2024/08/14, 04:14:33
    常见面试题
    屏蔽事件

    ← 常见面试题 屏蔽事件→

    最近更新
    01
    React Native 使用SVG
    08-13
    02
    Docker基础命令
    08-04
    03
    算数逻辑单元
    07-30
    更多文章>
    Theme by Vdoing | Copyright © 2021-2024 WeiXiaojing | 友情链接
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式