关于跨域以及解决思路

2019-04-10  本文已影响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>

二、跨域产生的原因

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

三、跨域的几种解决方案

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

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实现跨域的缺点?

3、根据服务方和请求方来确定

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

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

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

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

常用的反向代理:Nginx代理

上一篇下一篇

猜你喜欢

热点阅读