前端vue3 + vite + axios,后端node+nginx,解决跨域问题
跨域问题说明
本部分主要解释跨域和相关说明,具体解决方案可以前往解决方案查看。
跨域是什么?
跨域的根本问题就是浏览器里有一个同源策略的技术限制,就会导致你请求的链接被浏览器所拦截,导致请求失败。
同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。–来源 MDN
url的组成部分
一个请求的url一般由六部分组成
var url = 'https://blog.csdn.net:443/Youyo_littleboy?type=blog#someWhere'
//1.协议-[https://] 决定这一条url的网络进行数据交换的规则 类似的还有http、ftp、wss...
//2.域名-[blog.csdn.net] 进行dns服务器解析进而访问对应的ip地址
//3.端口-[:443] 用冒号连接对应数字,代表访问这个ip地址对应的端口,端口范围在0-65535
//4.请求路径-[/Youyo_littleboy] 这部分主要是后端对你请求的路径路由进行相关数据响应方案
//5.请求参数-[?type=blog] 用?连接type代表参数名,blog代表参数的值,当参数多的时候可以使用&连接
//6.锚点-[#someWhere] 锚点可以自动导向访问页的具备相同id的标签,类似目录的功能
什么才算同源?
url1 = 'http://blog.csdn.net:80/Youyo_littleboy'
url2 = 'http://blog.csdn.net:80/other_page'
url3 = 'http://blog.csdn.net/other_page'
/**
* url1 与 url2 与 url3 都属于同源
* 因为协议、域名、端口都一致
* http代表的是80端口,默认隐藏,同类型的还有https-443、ftp-22...
*/
情况问题复现
因为项目需要使用到axios技术,所有引用了axios技术包,对axios做了一些简单的配置就测试了,反面教材配置如下
request.js文件
import axios from "axios";
// 超时时间是5秒
axios.defaults.timeout = 5000;
// 允许跨域
axios.defaults.withCredentials = true;
// Content-Type 响应头
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded;charset=UTF-8";
// 基础url
axios.defaults.baseURL = 'https://www.xxx.com/';
/**
* 封装get方法
* 封装post方法
* ...此部分省略
*/
然后浏览器就出现了请求返回200,但是拿不到结果的情况。
以及喜提调试报错
Access to XMLHttpRequest at ‘https://www.xxx.com/user’ from origin ‘http://127.0.0.1:5173’ has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
解决方案
翻阅相关网络资料后,了解了一下跨域出现的情况和一部分解决方案,这里采取了其中的一种解决方案,更多的解决方案可以查阅该文档: 10 种跨域解决方案(附终极方案)。
前端部分
该部分主要对vite和axios进行相关配置
vite反向代理配置
配置vite.config.ts文件
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [vue(), vueJsx()],//其他配置,和本问题无关
server: {
proxy: {
'/api': {//反向代理的请求名
target: "https://www.xxx.com/",//此处写后端地址
changeOrigin: true,//默认是false,当为true时可以将当前ip改为目标url,故启用该功能
rewrite: path => path.replace(/^\/api/,'')//重写url,注意一定要和请求名一致
}
}
}
})
axios配置
import axios from "axios";
// 超时时间是5秒
axios.defaults.timeout = 5000;
// 允许跨域
axios.defaults.withCredentials = true;
// Content-Type 响应头
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded;charset=UTF-8";
// 基础url
axios.defaults.baseURL = '/api'; //注意此处一定要和vite设置的请求名一致
//推荐一些封装写法
/**
* 封装get方法
*/
export function get(url, params = {}) {
return new Promise((resolve, reject) => {
axios
.get(url, { params: params })
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err);
});
});
}
/**
* 封装post方法
*/
export function post(url, data = {}) {
return new Promise((resolve, reject) => {
axios
.post(url, data)
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err);
});
});
}
后端部分
Node部分
在启动app服务框架的对应文件加上此方法
//allow access-control
app.all('*',function(req,res,next){
//设置允许跨域的域名,*代表允许任意域名跨域,大项目并不推荐 * 可根据自身需求改变
res.header("Access-Control-Allow-Origin", "*");
//允许的header类型
res.header("Access-Control-Allow-Headers", "content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
})
Nginx部分
修改Nginx的配置文件
location / {
add_header Access-Control-Allow-Origin *;#允许 *[所有]域名资源
add_header Access-Control-Allow-Credentials true; #预检请求
}