前端如何解决跨域

第一篇掘金博客,我想研究一下跨域这个问题。校招面试常被问到的问题,什么是跨域?如何解决跨域问题?这是两个高频被问的两个问题,虽然理论上能将这个问题回答过去,可是真正在项目中遇到跨域问题就犯难了。今天这篇文章适合跟我同样的小白阅读。css

学完这篇文章,咱们能够回答出如下几个问题html

  • 什么是跨域?前端

  • 跨域问题的产生以及意义vue

  • CORS跨域资源共享node

  • 解决跨域请求jquery

  • 如何使用proxyTable 解决开发环境的跨域webpack

    之前咱们先后端不分离时代,咱们前端只须要写最基础的html、css,而后将文件发给后台开发人员。咱们都是用服务器来渲染的,这样前端与服务器的代码彻底在一块儿,在同一个web服务器里面,同一个服务不存在跨域这个问题。web

    后来随着前端飞速发展,想要实现异步、无刷新操做,咱们开始使用ajax实现异步无刷新操做,效果惊人,这时候部署还会将前端代码与服务器代码放在同一个web服务器上,这也不会形成跨域问题。这就属于同源策略,域名、协议、端口相同。想要同源,这就要求前端开发人员也得须要使用后端的编译器,好比eclipse,本身跑项目才能顺利开发前端代码。面试

什么是跨域

跨域实际上也叫作非同源策略请求。 谈到跨域问题,咱们必须先了解一下什么是同源策略?ajax

同源策略:它是由Netscape提出的一个著名的安全策略。如今全部支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。
域名,协议,端口,三者所有相同就是同源,其中一个不一样就是**跨域**

web服务器:  http://127.0.0.1:3000/index.html
接口地址:    http://127.0.0.1:4000/list

在这个项目中,域名相同,协议相同,端口号不同,跨域
复制代码

跨域解决方案:

一、JSONP实现跨域

原理:jsonp实现跨域的原理是跨域的服务端把客户端所须要的数据放进客户端本地的一个js方法里,进行调用,客户端在本地的js对返回的数据进行处理。这样就实现了不一样域名下的两个站点间的交流。

基于script无跨域限制帮我咱们带到服务器上,而后利用callback回调函数作一些咱们想作的事, callback=fun function fun(){//基于script无跨域限制帮咱们带到服务器上,而后把本地的函数传递给服务器,服务器就能够接到请求,同时也能拿到callback传过来的func、服务器一、准备数据json格式的 data={...} 二、给客户端返回数据func(+JSON.stringify(data)+) ,三、客户端拿到数据 注:一、func得是全局函数。二、JSONP须要服务器端的支持服务器端

script、img、link、iframe这些标签能够跨域

例以下面的代码,既能够访问本身的,也能够访问跨域的。
复制代码
客户端请求:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <title>Document</title>
</head>
<body>
</body>
<script>
//jquery支持jsonp请求
    $.ajax({
        //发送ajax
        url: 'http://127.0.0.1:8001/list',//请求地址
        method: 'get',   //请求方式只能是get方式,这也是jsonp跨域的一个缺点
        dataType: 'jsonp',  //=>执行的是JSONP请求
        success: res => {
            console.log(res)
        }
    })  //客户端
    console.log('aaa')
</script>

</html>
复制代码
服务端用node来实现:
let express = require('express'),
    app = express();
app.listen(8001, _ => {
    console.log('OK!')
})
app.get('/list', (req, res) => {
    let { callback = Function.prototype } = req.query  //解构出来,设置默认值Function.prototype匿名空函数,
    //callback与ajax的回调函数绑定
    let data = {
        code: 0,
        meg: '这就是我要返回的数据'
    }   //返回给服务器的数据
    res.send(`${callback}(${JSON.stringify(data)})`)//拿到的数据返回(注:数据服务器能够插入任何恶意代码)
})
复制代码

http://127.0.0.1:8001/list?callback=jQuery214085466902496328_1593939725240&_=1593939725241 

上面发了list请求,传了一个callback函数,这个函数是jquery帮咱们建立出来的随机的的全局函数。

response返回的结果以下图:jquery建立的随机全局函数包着咱们的数据,当咱们浏览器拿到这个结果之后,就会把全局函数执行。全局函数会帮咱们默认执行success执行,把数据传给res。
复制代码

jquery在这个过程当中帮咱们完成了取值的过程:

  • jquery帮咱们默认建立一个全局函数
  • 帮咱们默认建立script向咱们服务器发请求,
  • 帮咱们默认执行全局函数的时候,把success执行,拿到咱们的数据。

二、CORS实现跨域

CROS(Cross-Origin Resource Sharing)跨源资源分享。

CROS容许浏览器向跨源服务器发出XMLHttpRequest请求,克服了ajax不能跨源请求的限制🚫。 CROS通讯的主要在于服务器,只要服务器实现CROS接口,就能够实现跨域请求。

浏览器在头信息中增长一个Origin字段,从而发出CROS请求
   要支持CORS访问须要服务器在响应头中添加Access-Control-Allow-Origin,可使用*来表示容许全部域跨域访问。
复制代码

详细的介绍能够参考阮一峰老师的这篇文章:www.ruanyifeng.com/blog/2016/0…

三、 vue项目开发使用proxyTable 解决开发环境的跨域

这是我想重点介绍的,由于公司前端页面是基于vue实现的,前端使用vue-cli脚手架搭建的vue项目作开发的时候,项目自己启动本地服务须要占用一个端口。咱们在与后端服务器接口联调的时候,必定会产生跨域问题。大多数公司都是采用先后端分离的开发模式,必然会产生跨域。咱们尽可能在前端去解决跨域问题,避免更改后端代码。

如今不少项目使用webpack自动化构建前端项目,在webpack项目中咱们使用ProxyTable来实现跨域。 ProxyTable实现跨域原理:

ProxyTable底层采用了http-proxy-middleware,这是http代理中间件。
    咱们在项目根目录的config文件夹下找到的index.js文件
复制代码

(1)利用vue-cli脚手架搭建一个vue项目

下面的步骤是基于你已经安装了nodejs、npm,(能够安装一个全局的淘宝镜像cnpm速度会比较快) npm install cnpm -g --registry=https://registry.npm.taobao.org

步骤:

  • cnpm install -g vue-cli //全局安装vue-cli

  • cd进入你想放置项目的文件夹

  • 在当前文件夹下执行 vue init webpack

  • cnpm i //安装依赖包

  • npm run dev // 执行项目

  • 至此咱们已经利用vue-cli搭建好了vue项目

(2)配置跨域

打开刚刚搭建好的vue项目的config文件夹下的index.js文件,在proxyTable对象中填写须要被代理的api,

proxyTable: {
      //配置特定的请求代理到对应的API接口
      //请求接口为/HomeApi被代理到  http://10.64.61.129:3000/home
      "/HomeApi": {
        target: "http://10.64.61.129:3000/home",  //目标地址
        changeOrigin: true,  //是否开启代理
        pathRewrite: {
          '^/HomeApi': ''
        }
      },
      //请求的借口 /details被代理到  http://10.64.61.129:3000/details
      "/DetailsApi": {
        target: "http://10.64.61.129:3000/details",  // 目标地址
        changeOrigin: true,
        pathRewrite: {
          '^/HomeApi': ''
        }
      },
    },
复制代码

注:借口本来为/payment/list,为了匹配代理地址,咱们在前面加上/HomeApi,就能够被分发到/HomeApi中,所以咱们须要将接口地址写成/HomeApi/payment/list。被分配到指定的代理中,咱们经过写 pathRewrite:{'^/HomeApi': ''}重写路径,去掉咱们以前为了匹配代理而加上的/HomeApi。

参考: www.cnblogs.com/gpd-Amos/p/…

参考: www.cnblogs.com/liyuspace/p…

相关文章
相关标签/搜索