当前位置: 首页>前端>正文

前端配置axios跨域 前端实现跨域


文章目录

  • 前言
  • 跨域解决的方法
  • 1.JSONP
  • 2.CORS跨域资源共享
  • 3.http proxy => webpack webpack-dev-server
  • 4.nginx反向代理
  • 5.postMessage(跟Worker很像)
  • 6.WebSocket协议跨域
  • 总结



前言

为了加快请求响应时间,服务器进行分布式布局,将服务器分为:
web服务器:用于处理静态资源
data服务器:业务逻辑和数据分析
图片服务器

由于浏览器的同源策略,同源策略认为以下三者都一样就是同源,只要有一个不同就是跨域:

  • 协议
  • 域名
  • 端口号

导致需要用到跨域请求。

跨域解决的方法

1.JSONP

使用不存在跨域请求的限制的html标签发送get请求,比如以下标签:
-script
-img
-link
-iframe

jsonp实现:

服务器:

let express = require('express'),
  app = express();

app.listen(8001, () => {
  console.log("OK!");
})

app.get('/list', (req, res) => {
  let { callback = Function.prototype } = req.query;
  let data = {
    code: 0,
    message: "珠峰培训"
  };
  res.send(`${callback}(${JSON.stringify(data)})`)
})

客户端:

<!DOCTYPE html>
<html>
<head>
	<title>GoJSONP</title>
</head>

<body>
<script type="text/javascript">
	function jsonhandle(data){
		alert("age:" + data.age + "name:" + data.name);
	}
</script>

<script crossorigin="anonymous" integrity="sha384-rY/jv8mMhqDabXSo+UCggqKtdmBfd3qC2/KvyTDNQ6PcUJXaxK1tMepoQda4g5vB" src="https://lib.baomitu.com/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
	$(document).ready(function(){
		var url = "http://127.0.0.1:8001/list?callback=jsonhandle";
		var obj = $('<script><\/script>');
		obj.attr("src",url);
		$("body").append(obj);
	});
</script>
</body>
</html>

结果:

前端配置axios跨域 前端实现跨域,前端配置axios跨域 前端实现跨域_前端,第1张

问题:JSONP只能支持GET请求。

2.CORS跨域资源共享

做法:

1.客户端(发送ajax/fetch请求)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script src = "./node_modules/_axios@0.21.1@axios/dist/axios.js"></script>
  <script>
    axios.get('http://127.0.0.1:3001/list')
      .then(result =>{
        console.log(result);
      })
  </script>

</body>

</html>

2.服务器端设置相关的头信息(需要处理options试探性请求)

let express = require('express'),
  app = express();

app.use('*', function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*'); //这个表示任意域名都可以访问,这样写不能携带cookie了。为了保证安全
  //res.header('Access-Control-Allow-Origin', 'http://www.baidu.com'); //这样写,只有www.baidu.com 可以访问。
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
  res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');//设置方法

  if (req.method == 'OPTIONS') {
    res.send(200); // 意思是,在正常的请求之前,会发送一个验证,是否可以请求。
  }
  else {
    next();
  }
});

app.listen(3001, () => {
  console.log("OK!");
})

app.get('/list', (req, res) => {
  let data = {
    code: 200,
    message: "我是服务器的数据!"
  };
  res.send(data)
})

3.http proxy => webpack webpack-dev-server

我们配置如下:
webpack.config.js

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: "production",
  entry: './fun.js',
  output: { // 输出配置
    filename: './built.js', // 输出文件名
    path: resolve(__dirname, 'build/js') // 输出文件路径配置
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './please.html',
      filename: 'index.html'
    })
  ],
  devServer: {
    port: 3000,
    progress: true,
    contentBase: './build',
    open: true
    // proxy: {
    //   '/': {
    //     target: 'https://www.baidu.com/',
    //     changeOrigin: true
    //   }
    // }
  }
}

fun.js如下:

import axios from "axios"

axios.get('https://www.baidu.com/').then(res => {
  console.log(res);
})

打开webpack内置的服务器: npx webpack-dev-server。

会发生跨域,那么我们需要把devServer上的proxy注释去掉。就可以了。

这是Node中间件 代理实现的!

就是用Node来搭了一个代理服务器帮忙转发客户端的请求??毕竟服务器和服务器不存在跨域。

如果要发行呢??毕竟devServer 是方便我们调试。那么就需要用node来做代理了。

4.nginx反向代理

不需要前端干啥。其实就是nginx帮我们加了Access-Control-Allow-Origin的请求头啦。

5.postMessage(跟Worker很像)

我们先看看postMessage由谁来调用:

语法

otherWindow.postMessage(message, targetOrigin, [transfer]);
  • otherWindow其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。

另外一种说法是:

otherWindow

对将接收消息的窗口的引用。获得此类引用的方法包括:

  • Window.open (生成一个新窗口然后引用它),
  • Window.opener (引用产生这个的窗口,返回打开当前窗口的那个窗口的引用,例如:在window A中打开了window B,B.opener 返回 A.),
  • HTMLIFrameElement.contentWindow<iframe>从其父窗口引用嵌入式),
  • Window.parent(从嵌入式内部引用父窗口<iframe>
  • Window.frames +索引值(命名或数字)。

或者看看MDN上描述:

window.postMessage MDN

otherWindow.postMessage(message, targetOrigin, [transfer])
otherWindow: A reference to another window(发送方的引用)

message:Data to be sent to the other window.(要发送到接受方的数据)

targetOrigin:Specifies what the origin of otherWindow must be for the event to be dispatched(接收方的 源,还有必须要有监听message事件)

使用:

我们先建立两个不同源的服务器:

let express = require('express'),
  app = express();

app.use(express.static('./'));

app.listen(1001, () => {
  console.log("port of 1001 OK!");
})
let express = require('express'),
  app = express();

app.use(express.static('./'));

app.listen(1002, () => {
  console.log("port of 1002 OK!");
})

1001.html,这个文件跑在域名为127.0.0.1:1001的服务器上,用于向域名为127.0.0.1:1002的服务器发送数据:

<!DOCTYPE html>
<html lan上g="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
fuwfuq
<body>
  <h1>server1</h1>
  <iframe id="myframe" src="http://127.0.0.1:1002/1002.html" frameborder="0"></iframe>

  <script>
    myframe.onload = function () { //注意要onload之后,才可以用postMessage
      let iframeWindow = myframe.contentWindow;
      iframeWindow.postMessage("宁静致远", "http://127.0.0.1:1002/1002.html");
    }

    //监听B传递的信息
    window.onmessage = function (ev) {
      console.log(ev.data);
    }
  </script>

</body>

</html>

这里有个需要注意的问题,我们 发送方的引用,即调用postMessage() 那个引用的源要与接受方的源即postMessage()的第二的参数 要同源。

1002.html,这个文件跑在域名为127.0.0.1:1002的服务器上,用于向域名为127.0.0.1:1001的服务器发送和接收数据:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <h1>server2</h1>
  <script>
    //监听A发送过来的信息
    window.onmessage = function (ev) {
      console.log("server2 recevice message");
      ev.source.postMessage("recevice message", ev.origin);
    }
  </script>
</body>

</html>

结果:

前端配置axios跨域 前端实现跨域,前端配置axios跨域 前端实现跨域_服务器_02,第2张

这种方法本质是在一个页面上通过iframe标签打开不同源的其它页面,通过主页面与iframe交流的方法postMessage进行数据的交流。可以进行get和post请求。

6.WebSocket协议跨域


总结

前端跨域方案可以分为4个方向:

  1. 通过没有同源策略限制的Html标签实现数据请求。
  2. 在客户端建一个服务器代理。
  3. 请求加上access-control-change- 请求头。
  4. 使用websocket协议。



https://www.xamrdz.com/web/2tt1960206.html

相关文章: