美文网首页
关于跨域以及解决思路

关于跨域以及解决思路

作者: 前端葱叶 | 来源:发表于2019-04-10 16:55 被阅读0次

    本章内容目录:
    一、跨域相关概念的理解
    二、跨域产生的原因
    三、跨域的几种解决方案

    一、跨域相关概念的理解

    首先先了解以下几个概念:

    • "同源策略"

    同源策略,相同来源的策略。它是浏览器的一种约定,为了安全,浏览器页面禁止来自不同源的网页或脚本加载。

    • "同源"和"跨域"

    同源,即协议,域名、端口都相同。

    跨域,即协议、域名、端口有任何一个不相同。和同源的概念相反。

    我们都知道URL一般都是由协议、域名、端口、路径构成。

    A页面访问B页面,如果这两个页面URl的协议、域名、端口都相同,则表示他们同源,可以访问;反之,如果协议、域名、端口三个中有任何一个不相同,就表示跨域,访问被拒绝。

    如:http://leaf.com/test/index.html访问以下URL进行同源策略检查,查看是否跨域:

    URL 是否跨域 理由
    http://leaf.com/test2/index.html 没有跨域 其他相同,只是路径不同
    http://leaf.com/test/index2.html 没有跨域 其他相同,只是路径不同
    https://leaf.com/test/index.html 跨域了 协议不同
    http://leaf.com:8080/test/index.html 跨域了 端口不同
    http://leafice.com/test/index.html 跨域了 域名不同
    • 有哪些不受浏览器同源策略影响的脚本或标签?

    有src属性的标签是可以加载跨域资源的,不受浏览器同源策略的限制,如:<script>、<img>、<iframe>、<link>等。

    一个页面当中,js脚本、css样式文件、img图片的资源是可以和页面不同源的;它们可能是某个CDN地址。如我们平常引用的BootCDN
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

    二、跨域产生的原因

    • 浏览器“同源策略”的限制
      (使得不同域名的两个页面之间不能相互访问)
    • 请求方式Type为XHR请求
      (如果发送的不是XHR请求,json、js就算是跨域也不会报错)
    • 请求方和服务方不同源,即跨域
      (协议、域名、端口号有任何一项不同)

    只要满足以上的三个条件才有可能产生跨域。

    三、跨域的几种解决方案

    根据跨域产生的三个原因对应有以下三种解决思路:

    1、禁止浏览器校验,关闭"同源策略"(不推荐)

    指定参数禁止浏览器校验:
    --disable-web-security --user-data-dir

    (有时候可以做本地测试跨域使用,不依赖服务端)

    步骤:(针对chrome)
    1、必须关掉chrome打开的所有页面,否则不生效;
    2、新建chremo的快捷方式,并右键选择“属性”打开:

    打开新快捷方式的属性.png
    3、在“目标”处,添加--disable-web-security --user-data-dir,最后应用保存,添加后如图:
    image.png

    4、打开新快捷方式,会显示提示文案:如下图所示,说明已经禁止了浏览器的“同源策略”,输入你的本地预览地址,应该可跨域了:


    image.png

    缺点:需要客户端改动

    2、JSONP(常用跨域方案,需掌握)

    在页面中使用XMLHttpRequest请求不同域上的数据是不可以的,但是在页面上引入不同域的JS脚本确实允许的。(上边说了<script>不受浏览器同源策略的限制)
    (1)JSONP是什么?
    一种非官方协议;
    允许用户传递一个callback参数给服务端;

    (2)JSONP跨域的实现原理?
    由于 script 标签不受浏览器同源策略的影响,允许跨域引用资源。因此:

    JSONP实现原理:就是前端请求后台包装好的一段JSON数据,后台会把数据放在一个callback函数中,返回一个JS文件,前端只需动态引入这个JS文件,再去调用callback函数就可以访问数据了。
    注意:
    请求完之后这个JS就会被销毁,可以通过控制台打断点的方式验证。

    具体的实现思路步骤:
    ①JSONP发送请求时URL会添加一个查询字符串默认callback指定回调函数名,如参数callback=a指定回调函数的名为a;
    (callback=a的作用就是让后端知道前端调用函数的函数名,可以通过ajax中的jsonp指定查询字符串(默认callback)、jsonpCallback指定回调函数名)
    如:

        <script>
            function fetchData() {
                $.ajax({
                    type: "GET",
                    url: "xxxx",
                    dataType: "jsonp",
                    jsonp:"callback",//默认callback
                    /* 在一个 jsonp 请求中重写回调函数的名字。
                    这个值用来替代在 "callback=?" 这种 GET 或 POST 请求中 URL 参数里的 "callback" 部分
                    比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。*/
                    jsonpCallback: "leaf"
                    /* 自定义请求接口成功之后执行的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
                    类似:jQuery1111111111111_222222(["aa","bb","cc"])*/
                })
            }
            // 请求接口成功之后执行的回调函数
            function leaf(data) {
                console.log(data);
                // 执行代码
            }
        </script>
    

    ②后台如果发现传递过来的URL有callback参数,后台就知道这是一个JSONP请求;
    ③后台就会把返回的JSON数据用函数名a包裹起来,变成JS文件,这样JSON数据就变成了函数a里面的参数;
    ④前端动态引入这个JS文件,调用函数a就可以访问数据了;

    (3)JSONP实现跨域的缺点?

    • 服务器代码需要修改;
    • 支持GET请求;
      (如果指定请求方式为POST也是无效的,只能以GET方式请求);
    • 发送的不是XHR请求;
    3、根据服务方和请求方来确定

    (1)服务方:让服务器修改请求头支持跨域

    思路:从a域名调用b域名的时候,b域名返回的数据中添加一些字段告诉浏览器:我允许a域名调用。如果浏览器通过校验,就不会报跨域问题。

    (2)请求方:隐藏跨域,即设置反向代理

    通过一个代理,然后从浏览器发出去的否是a域名的请求,在代理里面,把指定的url转到b域名里面,在浏览器看来,它就是同一个域名,就没有跨域问题。
    即:访问同一个域名的两个不同url,最后会去了2两个不同的服务器。

    常用的反向代理:Nginx代理

    相关文章

      网友评论

          本文标题:关于跨域以及解决思路

          本文链接:https://www.haomeiwen.com/subject/eeyniqtx.html