最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端——跨域

    正文概述 掘金(爱创课堂前端技术分享)   2020-11-26   653

    跨域(Cross-Origin)

    总结一句话:跨域是不可能靠前端单方面解决的,不管是怎么解决,都需要服务端的支持

    同源策略

    什么是同源策略

    说到前端跨域,那就不得不说同源策略,因为造成前端会有跨域问题的“罪魁祸首”就是浏览器的同源限制策略

    上面这段话说的直白一点就是,我在一个域名地址下的网页,如果请求一个受到同源策略限制的地址接口的时候,就会报错,这是为了在我的网页下请求别的地址的文件可能是恶意代码,造成不必要的问题。默认从自己同一个源请求的文件就是。。。安全可信赖的。

    什么样是同源,什么样是非同源

    那按照同源策略,不同源的是不能进行请求等操作的,那什么样的是同源,什么样的又不是同源呢(我想从事前端的小伙伴多多少少应该都应该知道);
    只要满足

    协议、主机、端口

    一致,则两个页面具有相同的源

    例子:假如我们从http://www.zhanwuzha.com/home/index.html向以下地址发送请求

    1. http://www.zhanwuzha.com/home/detail.html 成功,路径不同
    2. http://www.zhanwuzha.com/description/detail.html 成功,路径不同
    3. https://www.zhanwuzha.com/home/list.html 失败,协议不同(http 和 https)
    4. http://www.zhanwuzha.com:8848/home/manange.html 失败, 端口不同(默认80 和 8848)
    5. http://mobile.zhanwuzha.com/home/secret.html 失败,域名不同(www 和 mobile)

    好,我们现在知道什么情况算是同源了,因为不同源造成的请求错误,发送的请求就会跨域,那我们在实际生产、开发环境可能都会遇到,那我们现在着手解决这个问题

    JSONP

    我相信只要从事过前端的小伙伴用没用过不说,但应该都听说过JSONP这个技术。毕竟面试问不问,准备的时候都会了解。那JSONP到底是怎么解决跨域的呢?

    src和href属性

    刚才说了只要

    协议、主机、端口

    不一致,就会有跨域的问题,但是,HTML的标签中有一个属性是可以请求外部地址的,那就是srchref属性⬇️

    <img src="http://www.zhanwuzha.com/media/001.jpeg"></script>
    <link rel="stylesheet" href="http://www.zhanwuzha.com/css/reset.css"> 
    
    <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
    

    以上这种引用,我们肯定都知道是可以的,可以请求外部地址的js或者css,请求cdn服务器上的公共资源,并且不会出现问题,所以根据src的这一个特性,优秀的工程师们想到一个解决跨域的办法,俗称JSONP

    JSON with Padding

    下面我们就来看看JSONP到底是怎么实现的跨域请求
    大家都知道<script>标签不管是从哪请求回来的js文件,都会立即执行,好,那我们看下面的代码⬇️
    index.html

    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>JSONP</title>
      <script src="http://www.zhanwuzha.com/jsonp/js/index.js"></script>
    </head>
    <body>
    </body>
    </html>
    

    jsonp/js/index.js

      console.log('我是src请求回来的js文件,我被执行了')
    

    不出意外,我们浏览器的控制台肯定会输出‘我是src请求回来的js文件,我被执行了’这句话,那我们再来看下面的示例 index.html

    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>JSONP</title>
      <script>
        function print(str) {
          console.log(str)
        }
      </script>
      <script src="http://www.zhanwuzha.com/jsonp/js/index.js"></script>
    </head>
    <body>
    
    </body>
    </html>
    

    jsonp/js/index.js

      print('我是src请求回来的js文件,我被执行了')
    

    不出意外的话,这个也会输出‘我是src请求回来的js文件,我被执行了’这句话,但是跟刚才不同,我们是实现声明好了一个叫print的方法,然后在jsonp/js/index.js返回的js文件中,调用这个方法,然后顺利的执行,那我们是不是可以通过动态添加<script>的标签,可控的去请求远端js并执行,接下来我们来看一个完整版的请求⬇️
    index.html

    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>JSONP</title>
      <script>
        function print(data) {
          console.log(`我叫${data.name}`);
          console.log(`我今年${data.age}岁`);
          let jsonpScript = document.getElementsByClassName('jsonpScript')[0];
          document.body.removeChild(jsonpScript);
        }
        function jsonpRequest(callback) {
          let jsonpScript = document.createElement('script');
          jsonpScript.src = `http://www.zhanwuzha.com/jsonp/js/index.js?callback=${callback}`;
          jsonpScript.className = 'jsonpScript';
          document.body.appendChild(jsonpScript);
        }
      </script>
    </head>
    <body>
      <button onclick="jsonpRequest('print')">发个JSONP请求</button>
    </body>
    </html>
    

    jsonp/js/index.js

      print({
        name: '前端战五渣',
        age: 18
      })
    

    这样我们就实现了点击页面上的按钮,我们去执行jsonpRequest()方法,并且传进去参数"print"的字符串作为回调函数的名字,显示在页面上添加一个<script>标签并且src的地址为http://www.zhanwuzha.com/jsonp/js/index.js?callback=print,等js文件请求回来以后执行我们先前传入的名为"print"的方法,并且传入了一个对象作为参数,这时控制台就会输出两句话‘我叫前端战五渣\n 我今年18岁’。
    后端拿到了callback=print只需要进行字符串拼接,调用名为print的方法,并且把需要传回来的数据作为参数拼进去,jsonp/js/index.js就是后端动态生成的
    这样我们就完整的进行了一次JSONP的请求
    其实JSONP并不算真正意义上的AJAX请求,只是请求了一个js文件并且执行了,而且这种跨域方法只能进行GET请求

    CORS

    接下来我们要讲得这个CORS方法的全称是Cross-origin resource sharing,中文名叫“跨域资源共享”,这可能是目前很多公司解决跨域问题的方法,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

    这一节我们能知道其实同源策略不仅仅是浏览器这边做了限制,在服务端也是有限制的

    简单请求

    只要满足以下条件的请求,就属于简单请求

    1. 请求方法为HEAD、GET或者POST中的一种
    2. HTTP的头信息不超过以下几种字段AcceptAccept-LanguageContent-LanguageLast-Event-ID以及Content-Type的值只限于application/x-www-form-urlencodedmultipart/form-datatext/plain三个

    对于简单请求来说,从浏览器发出请求的时候,浏览器会自动在请求头中添加一个字段Origin,值为发出请求网页的源地址

    前端——跨域

    服务端根据这个值,决定是否同意这次请求,如果Origin的值不在指定的许可范围,服务端返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。 如果Access-Control-Allow-Origin字段正好跟带过去的Origin的值一样,则返回对应的数据,完成一次请求。

    非简单请求以及option请求

    非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json

    在进行非简单请求之前,浏览器会在正式请求之前发送一次预检请求,这就是有时候我们会在控制台中看到的option请求,就是说,正式请求之前,浏览器会去问服务端我这个地址能不能访问你,如果可以,浏览器才会发送正式的请求,否则报错。

    CORS总结

    总的来说,CORS实现跨域的方法就是根据请求头的Origin值和响应头的Access-Control-Request-HeadersAccess-Control-Request-Method的值进行比对,通过了就可以请求成功,没通过就请求失败。

    反向代理

    node反向代理

    如果我们用的是node起的前端服务,那我们可以使用node来直接进行反向代理

    前端——跨域

    以上是我用express框架起的服务,我们只需要引入一个处理代理的插件,然后如图中的配置,代理接口地址,然后配置一个target,就是需要代理到的地址,起服务,监听8848端口;这时我们假如我们的ip地址是http://127.0.0.1:8848,我们就可以访问当我们的页面,然后从页面中向http://127.0.0.1:8848/a以及http://127.0.0.1:8848/b接口发送请求的时候,前端服务接到请求会向http://127.0.0.1:8080/a以及http://127.0.0.1:8080/b的接口请求,然后再返回数据。这就用反向代理实现了跨域请求,因为我们的前端服务在8848端口,而要请求的端口在8080,所以实现了一次完美的跨域请求。

    不仅用node可以反向代理,有一大部分的公司用的是nginx进行的代理(nginx没怎么玩过,就不献丑了),或者进行CORS来解决跨域,所以解决的方案一样,只是工具的选择不同

    为什么反向代理可以跨域

    如上面所说,我们在前端服务器上代理了后端的接口,我们只需要访问跟页面在同一源地址下的接口就行了,但是这是为什么呢?

    一开始我们就说过,同源策略只是浏览器的一个安全策略,只适用于浏览器向服务器发送请求的时候,当服务器跟服务器发送请求的时候,自然就没有这么一层限制,只要是接口,就会返回。

    有人说那不需要权限验证吗??当然需要了,但是在权限不通过的时候,也是会请求成功200的,只是返回的是“需要登录”等信息,但是如果是浏览器跨域访问这个接口,返回的只能是一个错误。

    反向代理和正向代理

    什么是正向代理和反向代理,我先来一张图

    前端——跨域

    正向代理

    什么是正向代理呢,众所周知的科学上网,就是一个很典型的实例,

    前端——跨域

    当我们从客户端没有办法访问到目标服务器的时候,我们可以通过正向代理,把请求代理到一个有权访问到目标服务器的代理服务器,然后让代理服务器去请求目标服务器,拿到数据再返回来,进而实现科学上网的目的。在整个过程中,我们用户,客户端其实是很清楚实际数据是哪台服务器返回来的,很明显是目标服务器返回的数据,只是中间经过了别人一手而已。

    反向代理

    反向代理的例子其实不用再说了,就是我们将node时候的作用,在上面的反向代理的图中,我们可以看到,是各个客户端都会向代理服务器发送请求,然后代理服务器再向各个真正获取数据的服务器发送请求获取数据。相对正向代理,反向代理的客户端,是不清楚数据到底是从哪台服务器获取的,他们只知道是从代理服务器返回的数据,在反向代理的流程中,其实在客户端的眼里代理服务器就是目标服务器,并不知道存在真正的目标服务器

    总结

    到底是正向代理还是反向代理,只需要判断客户端知不知道真正返回数据的服务器在谁,知道就是正向代理,不知道就是反向代理

    }
    <html lang="en">
    <head>
        前端学习培训、视频教程、学习路线,可以添加威信:kaixin666haoyun 分享给大家前端学习资料。
    </html>    }
    

    起源地下载网 » 前端——跨域

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元