首页 前端知识 什么是跨域,如何解决跨域(前后端)

什么是跨域,如何解决跨域(前后端)

2024-05-09 10:05:10 前端知识 前端哥 440 14 我要收藏

什么是跨域

跨域:指的是在网页端,发起一个跨越不同域名(协议、端口号)的HTTP请求的过程。
例如:当一个页面的URL为http://a.com,通过Ajax向http://b.com发送请求,就是一个跨域请求。

跨域问题是由浏览器的同源策略所引起的。同源策略限制了JS代码只能读取与其来源页面具有相同域名的数据。具体而言,同源策略是一种浏览器安全策略,它通过检查来源URL(协议 + 域名 +端口)是否与目标URL来源是否相同来决定是否允许跨域访问。同源策略主要限制以下四种行为

  1. Cookie、LocalStorage、IndexedDB 等存储性质的操作限制无法读取、写入非同源网站的Cookie等数据。
  2. DOM操作的各种API(如document.href等)限制无法获取和修改非同源网站的DOM对象。
  3. AJAX请求限制无法向非同源网站地址发送 AJAX 请求。
  4. window.open()方法限制无法打开非同源网站访问页面。`

举例说明

假设有一个在本地localhost:8080上的静态网站,并且它得到一个需要跨域请求的数据服务在www.server.com后端运行。(1)请求方式一:使用JavaScript内置XMLHttpRequest对象

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.server.com/data.json', true);
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        console.log(xhr.responseText);
    }
}
xhr.send();

出现如下错误:

XMLHttpRequest cannot load http://www.server.com/data.json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

错误提示中有重要提示“没有'Access-Control-Allow-Origin' header”,这是一个安全机制,它的作用是防止非同源的交互。因此,服务器需要设置 Access-Control-Allow-Credentials, Access-Control-Allow-Origin 和 Access-Control-Allow-Methods 以允许跨域请求

如何解决跨域

1. jsonp跨域

JSONP(JavaScript Object Notation with Padding)使用一个<script>标签发送一个回调函数到服务端,服务端将一些用JSON表示的数据填入该回调函数中(也就是说服务端返回这个函数的调用,将服务daunt的数据以该函数的参数的形式发送给客户端),最后将字符串形式返回客户端。具体实现:

客户端

$.ajax({
    url: 'http://www.server.com/data.json',
    dataType: 'jsonp',
    jsonpCallback: 'callback',
    success: function(data){
        console.log(data);
    },
    error: function(XMLHttpRequest, textStatus, errorThrown){
        console.log('Error occurred: ' + textStatus);
    }
})

服务端

app.get('/data.jsonp', function(req, res) {
    var data={'name':'Tom', 'age':'25'};
    var jsonData = JSON.stringify(data);
    var callback = req.query.callback;  // callback=parseResponse
    var resData = callback + '(' + jsonData + ')'; //parseResponse({"name":"Tom","age":"25"})
    res.send(resData);
});

JSONP的原理:是利用\<script>标签不受同源策略约束的特点通过动态创建并插入\<script>标签来实现跨域请求
如下,用<script>标签链接了一个callback函数,服务器返回JSON数据并把数据作为函数的参数传递进去,页面执行callback函数将数据作为参数来处理

<script type="text/javascript">
   function callback(data){
       // other code here
   }
   var myScript = document.createElement("script");
   myScript.src = "http://www.server.com/data.json?jsonp=callback";
   document.body.appendChild(myScript);
</script>

注意:jsonp只支持get方式发送请求

2. 跨文档消息传递(postMessage)

这个大家可以参考这篇文章postMessage解决iframe内嵌vue项目跨域问题

3. cors设置相应头

下面以CORS为例,详细说明如何实现跨域访问:

  1. 服务端设置响应头

在服务端的响应中设置以下响应头:

Access-Control-Allow-Origin:
指定了允许跨域访问的源,可以是单个域名或者 * 代表允许所有域名访问。

Access-Control-Allow-Headers:
表示允许跨域请求携带的自定义头信息。

Access-Control-Allow-Methods:
表示允许跨域请求的请求方法。

Access-Control-Allow-Credentials:
表示跨域请求是否允许携带cookie。

下面是一个允许http://localhost:8080 跨域访问的响应头设置:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS
Access-Control-Allow-Credentials: true
4. 服务端配置代理服务器实现跨域

配置代理服务器实现跨域的一般步骤:

  1. 创建代理服务器
    代理服务器可以使用任何基于Node.js的框架来创建,例如Express.js、Koa.js或Hapi.js。在本例中,我们将使用Express.js。

  2. 安装跨域包
    使用npm安装cors包,这是Express.js的一个中间件,它允许应用程序接受来自不同源的HTTP请求。

  3. 配置Express.js应用程序
    在应用程序中,配置中间件以接受来自任意来源的请求,并将它们重定向到代理服务器。下面是Express.js应用程序的示例代码:

const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors());

app.get('/api/data', (req, res) => {
    // 这里是API逻辑,返回数据
});

app.listen(3000, () => {
    console.log('服务器运行在端口3000');
});
  1. 配置代理服务器
    代理服务器将请求重定向到另一台Web服务器。在本例中,我们将使用http-proxy-middleware包。安装它并使用以下代码配置代理服务器:
const express = require('express');
const cors = require('cors');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();

app.use(cors());

app.use('/api', createProxyMiddleware({
    target: 'http://localhost:3000',
    changeOrigin: true,
}));

app.listen(4000, () => {
    console.log('代理服务器运行在端口4000');
});

在上面的代码中,我们使用createProxyMiddleware方法创建了一个代理中间件,并将所有以/api开头的请求都重定向到http://localhost:3000

现在我们的代理服务器已经配置好了。我们可以将所有来自客户端(例如一个Vue.js或React应用程序)的请求发送到http://localhost:4000/api/data,代理服务器将它们重定向http://localhost:3000/api/data,然后将响应返回给客户端。

具体来说,对于Vue.js应用程序,可以在axios库中设置baseURL选项来指向代理服务器地址http://localhost:4000

// 配置axios库
import axios from 'axios';

axios.defaults.baseURL = 'http://localhost:4000';

// 在组件中使用axios
axios.get('/api/data')
    .then(response => console.log(response.data))
    .catch(error => console.error(error));

这样就可以在Vue.js应用程序中发送跨域请求了。其他框架的方式类似。

5. vue proxy配置代理跨域

Vue项目中,可以通过在vue.config.js中配置proxy来实现跨域请求。

首先,创建vue.config.js文件:

// vue.config.js

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000', // 要代理到哪个域名下
        changeOrigin: true, // 允许跨域
        pathRewrite: {
          '^/api': '', // 将请求路径中的/api替换为空
        },
      },
    },
  },
};

上述代码表示,如果接口请求路径以/api开头,那么就会被代理到http://localhost:3000域名下,从而实现跨域访问。

例如,如果发起如下请求:

axios.get('/api/user')

实际上会被代理成:

axios.get('http://localhost:3000/user')

这样就能够解决跨域问题了。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/7665.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!