前言
Q:跨域不是说是浏览器引起的吗?怎么后端配置cors后就不会跨域了
A:您说得对,跨域问题是由浏览器引起的,但后端配置 CORS 头可以告诉浏览器允许哪些跨域请求。浏览器在发起跨域请求时,会发送一个预检请求(preflight request),检查服务器是否允许该请求。如果服务器返回的 CORS 头中包含了正确的设置,浏览器就会允许该跨域请求。
换句话说,后端配置 CORS 头实际上是在告诉浏览器:“我(服务器)允许你(浏览器)从这些特定的域名(或一些其他配置)发起跨域请求。”这样,浏览器就不会再阻止这些跨域请求了。
所以,尽管跨域问题是由浏览器引起的,但通过在后端配置正确的 CORS 头,可以解决跨域问题,使得浏览器不再阻止跨域请求。
正文
有问题就找解决方案,从解决方案找到合适自己项目的:
解决前端跨域问题方案
方案一 CORS:
node代码:
var express = require('express')
var cors = require('cors')
var app = express()
function handleCors(req, res, next) {
// 允许的请求方法
res.setHeader(
'Access-Control-Allow-Headers',
'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , reqSource,xx'
)
// 允许的请求方法
res.setHeader('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS')
// 允许携带凭据(cookies)
res.setHeader('Access-Control-Allow-Credentials', true)
// 从请求头中获取 Origin 值
const origin = req.headers.origin
// 请求包含凭据(如 cookies、HTTP 身份验证或 TLS 客户端证书)时,不能使用通配符 *。
// 检查请求来源是否允许跨域访问
if (origin && (origin === 'http://127.0.0.1:8084' || origin === 'http://127.0.0.1:5173')) {
// 允许特定的来源跨域访问
res.setHeader('Access-Control-Allow-Origin', origin)
}
// 如果是 OPTIONS 请求,直接返回,不进入下一个中间件
if (req.method === 'OPTIONS') {
return res.send({ code: 204, err: '' })
} else {
next()
}
}
app.use(handleCors)
// 允许所有源访问
app.use(
cors({
credentials: true,
// // 请求包含凭据(如 cookies、HTTP 身份验证或 TLS 客户端证书)时,不能使用通配符 *。
origin: 'http://127.0.0.1:5173'
})
)
// 或者允许特定的来源
// app.use(cors({ origin: 'http://your-frontend-domain.com' }));
// 定义路由和其他中间件
app.get('/api/data', (req, res) => {
res.json({ message: 'Hello from Node.js!' })
})
app.post('/api/info', (req, res) => {
res.json({ message: 'info from Node.js!' })
})
// 启动服务器
const port = 3000
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
vue代码:
<template>
<div class="sass_box" @click="handleTestHttp"> sdafsdfasdf </div>
</template>
<script setup lang="ts">
import axios from 'axios'
async function handleTestHttp() {
try {
// let res = await http.post('/api/info')
// console.log('res', res)
axios.defaults.baseURL = 'http://localhost:3000'
axios.defaults.headers['Content-Type'] = 'application/json'
axios.defaults.withCredentials = true
axios
.get('/api/data')
.then((res) => {
// fetch('http://localhost:3000/api/data')
// .then((response) => response.json())
// .then((data) => {
console.log(res)
})
.catch((error) => {
console.error('Error:', error)
})
} catch (error) {
console.log('error', error)
}
}
</script>
<style lang="scss"></style>
方案二 Nginx反向代理:
前端地址
http://127.0.0.1:5173
后端地址
http://127.0.0.1:3000
Nginx配置
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8084;
server_name 127.0.0.1;
location / {
proxy_pass http://127.0.0.1:5173;
}
location ~ /api/ {
# 去掉/api/前缀
# rewrite ^/api/(.*) /$1 break;
# 代理到后端服务器
proxy_pass http://127.0.0.1:3000;
}
}
}
实际使用前端地址http://127.0.0.1:3000访问,请求后端接口只需添加后端路由,如请求接口http://127.0.0.1:3000/api/info,那么只要fetch(‘/api/info’)
测试nginx配置有没有问题
nginx -t
编辑器保存时候出现编码问题,后面我使用vscode没出现这个问题:
方案三 vite.config.ts配置server.proxy:
server: {
origin: 'http://127.0.0.1:8080',
proxy: {
// 字符串简写写法:http://localhost:5173/foo -> http://localhost:4567/foo
// '/foo': 'http://localhost:4567',
// 带选项写法:http://localhost:5173/api/bar -> http://jsonplaceholder.typicode.com/bar
'/api': {
target: 'http://127.0.0.1:8084', // 后端地址
changeOrigin: true
// rewrite: (path) => path.replace(/^\/api/, ''),
}
}
},
前端地址正常访问,请求后端接口只需添加后端路由,如请求接口http://127.0.0.1:3000/api/info,那么只要fetch(‘/api/info’)
方案四谷歌游览器去掉同源策略
在进行前端开发设置谷歌浏览器跨域时遇到了问题,百度上说的方法不管怎么设置就是不能跨域,在死怼中发现了可以这样设置跨域(详见三)
总结三种方法:
一、49版本以前的设置:
在桌面chrome快捷方式的属性中的目标输入框添加 --disable-web-security 添加部分与前面字符之间有空格(有文章说目标引号结尾的加 --args --disable-web-security,反正我没成功)
二、49版本以后的设置:
1.在电脑上新建一个目录,例如:C:\MyChromeDevUserData
2.在属性页面中的目标输入框里加上 --disable-web-security --user-data-dir=C:\MyChromeDevUserData,–user-data-dir的值就是刚才新建的目录(参考上面截图)
三、如果以上两种方法失败,用以下方法
1.通过桌面快捷方式打开文件位置,找到谷歌浏览器安装位置,看到有个chrome.exe文件
2.在电脑上新建一个目录,例如:C:\MyChromeDevUserData
3.打开cmd命令行,进入快捷方式位置 例如 cd C:\Program Files (x86)\Google\Chrome\Application
4.通过命令行启动谷歌浏览器 C:\Program Files (x86)\Google\Chrome\Application>chrome.exe --disable-web-security --user-data-dir=C:\MyChromeDevUserData (红色部分为启动命令以及跨域设置)
上面第三种方式我觉得和权限有关,非得用命令行启动才生效,但是我做了前面两种方式并以管理员方式启动依然无效。但是每次按第三种操作又麻烦,就偷个懒在桌面写个脚本来启动,脚本内容就是第三种方法的命令,文件命名格式xxx.bat,例如我的:
各位根据自己情况做相应更改即可,双击脚本文件即可启动chrome浏览器,并且打开跨域模式
方案五JSONP
script标签不受同源策略影响,回调函数名需要与后端返回的一直
方案六img
img标签不受同源策略影响,无回调函数