前端跨域问题详解与解决方案指南

什么是跨域问题

跨域问题通常是由浏览器的同源策略(Same-OriginPolicy,SOP)引起的访问问题

同源策略是浏览器的一个重要安全机制,它用于限制一个来源的文档或脚本如何能够与另一个来源的资源进行交互

同源策略的定义

同源策略要求两个URL必须满足以下三个条件才能认为是同源

协议(Protocol):例如,http和https是不同的协议。

主机(Host):例如,www.example.com和api.example.com是不同的主机

端口(Port):例如,默认的8080和8081端口被认为是不同的端口

只有当两个URL的协议、主机和端口都相同时,才被认为是同源。否则,浏览器会认为它们是跨域的

跨域问题的产生和前后端分离的发展密切相关

在早期 服务器端染的应用通常不会有跨域问题 因为前端代码和后端API都是在同一个服务器上运行的

随着前后端分离的出现,前端代码和后端API经常部署在不同的服务器上,这就引发了跨域问题

例如,一个网站的静态资源(HTML、CSS、JavaScript)可能部署在www.zhaimou.com上,而API接口则部署在api.zhaimou.com上浏览器在发现静态资源和API接口不在同一个源时,就会产生跨域问题

跨域常见的解决方案

方案一:静态资源和API服务器部署在同一个服务器中;

js 复制代码
//后端server.js
const express = require('express');

const path = require('path');

const app = express();

const port = 3000;

  

// API 路由示例

app.get('/api/greeting', (req, res) => {

res.json({ message: 'Hello from the API!' });

});

  

// 提供前端静态资源

app.use(express.static(path.join(__dirname, 'public')));

  

// 捕获所有请求并返回前端的 index.html

app.get('*', (req, res) => {

res.sendFile(path.join(__dirname, 'public', 'index.html'));

});

  

app.listen(port, () => {

console.log(`Server is running on http://localhost:${port}`);

});

前端相关代码

xml 复制代码
//public/index.html
<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Simple App</title>

</head>

<body>

<h1 id="greeting">Loading...</h1>

<script>

fetch('/api/greeting')

.then(response => response.json())

.then(data => {

document.getElementById('greeting').textContent = data.message;

})

.catch(error => {

console.error('Error fetching data:', error);

});

</script>

</body>

</html>

方案二:CORS,即是指跨域资源共享;

跨源资源共享(CORS,Cross-Origin Resource Sharing跨域资源共享)

它是一种基于httpheader的机制:

该机制通过允许服务器标示除了它自己以外的其它源(域、协议和端口),,使得浏览器允许这些origin访问加载自己的资源。

js 复制代码
const express = require('express');

const cors = require('cors');

const app = express();

  

app.use(cors({

origin: 'http://*****.com', // 允许的源

methods: ['GET', 'POST'], // 允许的 HTTP 方法

allowedHeaders: ['Content-Type', 'Authorization'] // 允许的 HTTP 头部

}));

  

app.get('/api/data', (req, res) => {

res.json({ msg: 'hello cors' });

});

  

app.listen(3000, () => {

console.log('Server is running on port 3000');

});

方案三:本地node代理服务器(Webpack/Vite中就是它)

在服务器端,跨域问题并不存在。服务器与服务器之间的通信不会受到浏览器的同源策略限制。这意味着,你可以在服务器上创建一个代理,将请求转发到另一个服务器,并从中获取数据而无需考虑跨域问题。这种做法在实际应用中是非常常见的。Vite、Weppack前端构建工具都是这样做的,Vite、Webpack它们的底层原理如下:创建开发服务器

使用Nodejs的http模块创建一个本地开发服务器,监听特定端口(如3000)。

这个开发服务器负责处理所有的前端请求,包活静态文件、热模块普换(HMR)、API代理等

使用http-proxy实现代理

vite或者Webpack使用http-proxy或httpproxy-middleware来创建代理中间件。代理中间件会拦特定路径的请求,并将这些请求转发到目标服务器。

js 复制代码
const express = require('express');

const { createProxyMiddleware } = require('http-proxy-middleware');

  

const app = express();

  

// 设置代理中间件

app.use('/api', createProxyMiddleware({

target: 'http://localhost:8080', // 目标服务器地址

pathRewrite: {

'^/api': '', // 重写路径,将/api前缀去掉

},

}));

  

// 启动服务器

app.listen(3000, () => {

console.log('代理服务器启动成功,监听3000端口~');

});

方案四:Nginx反向代理

在这里不做展开

不常见的方案:

jsonp:现在很少使用了;

postMessage:有兴趣了解一下吧;

websocket:为了解决跨域,所有的接口都变成socket通信

如果对你有所帮助的话就点个关注吧 会持续更新技术文章

相关推荐
慢慢雨夜1 小时前
uniapp 苹果安全域适配
java·前端·uni-app
凄凄迷人1 小时前
前端基于Rust实现的Wasm进行图片压缩的技术文档
前端·rust·wasm·图片压缩
史努比的大头1 小时前
前端开发深入了解性能优化
前端
码农研究僧1 小时前
Java或者前端 实现中文排序(调API的Demo)
java·前端·localecompare·中文排序·collator
guangzhi06331 小时前
JVM本地方法栈
java·jvm·面试
吕永强2 小时前
HTML表单标签
前端·html·表单标签
范特西是只猫2 小时前
echarts map地图动态下钻,自定义标注,自定义tooltip弹窗【完整demo版本】
前端·javascript·echarts
麒麟而非淇淋2 小时前
AJAX 进阶 day4
前端·javascript·ajax
图灵苹果2 小时前
【个人博客hexo版】hexo安装时会出现的一些问题
前端·前端框架·npm·node.js
IT-陈3 小时前
app抓包 chrome://inspect/#devices
前端·chrome