前言
在前后端分离的开发模式中,前端时常会遇到提示接口跨越而无法获取到数据的问题。在本文中只要介绍了跨域产生和解决原理,并提供一些解决办法。一、产生原理
1. 产生条件
- 跨越是产生于浏览器的 “同源策略” ,仅在浏览器会出现(小程序、postman等都不会)
- 域名出现以下不同的都会产生
- 协议:http、https
- 域名:www.baidu.com、cn.bing.com …
- 端口:8000,8080…
2. 如何产生
- 浏览器的同源策略是为了保护好客户端、服务器免受恶意攻击而进行的配置
- 当A源浏览器的网页 向 B源的服务器地址(不满足同源策略,满足同源限制)请求对应信息,就会产生跨域
- 跨域请求默认情况下会被浏览器拦截,除非对应的请求服务器出具标记说这个A源是允许拿B源的东西的
3.跨域的拦截原理
1)A源浏览器的网页 向 B源的服务器地址发送请求(首先发送请求的时候浏览器是不可能拦截的,因为浏览器不确保请求的服务器地址允不允许跨域)
2)请求开始传输 达到 B源的服务器
3)B源的服务器 收到请求,返回响应数据
4)响应数据到达浏览器,浏览器查看数据源是否有 配置跨越的身份标记
5)若有则响应给客户端,没有则拦截数据(即 A源浏览器的网页 拿不到响应数据)
注:跨越限制是服务器已经响应了东西,但是浏览器不给你,不是说服务器没响应东西二、解决办法
1. 开发时态
前端可以使用 构建工具或者脚手架或者第三方库的proxy 代理配置来解决这个问题
- 比如使用 vite 配置代理:
vite配置跨域
├─ index.html
├─ main.ts
├─ package-lock.json
├─ package.json
├─ README.md
└─ vite.config.ts
// vite.consig.ts
import { defineConfig } from 'vite'
export default defineConfig({
server:{
proxy: {
// 需要代理的字段
'/baidu': {
// 代理到的服务器地址
target: 'https://www.baidu.com/',
changeOrigin: true,
// 是否需要替换代理字段 ,这里为替换为空
rewrite: (path) => path.replace(/^\/baidu/, '')
},
}
}
})
- 请求测试:
// main.ts
import axios from "axios";
// 不需要设置 baseUrl
axios.get('/baidu').then(res=>{
console.log(res);
})
- 效果:
不同的构建工具有不同的配置方法,查看对应的官方文档即可
解决原理:
1)构建工具或者脚手架会搭建本地服务器用于启动项目
2)当我们发送请求时,浏览器会先帮我们做一步拼接 —> http://127.0.0.1:8000/baidu(默认本地服务器 + 后缀)
3)浏览器拼完以后,按照请求地址,请求会被发送到本地服务器
4)本地服务器发现这个地址(如上面的 “/baidu”)有配置过代理策略,然后它会根据策略的描述对象,代理的目标地址 “进行再次请求”
5)本地服务器对 url 进行替换、拼接等操作后向真正需要请求的 url 发送请求(如上面会向:“https://www.baidu.com/” 再次发送请求)
6)由于本地服务器 在node端运行不存在跨域,所以可以正常拿到数据,然后再响应给浏览器
7)浏览器拿到本地服务器响应的数据,由于数据来源为本地服务器,所以不存在跨域问题,故正常响应给用户
2. 生产时态
生产时态我们一般是交给后端去处理跨域
- 通常情况下我们项目上线时,都是 “后端服务+前端代码” 放在同一个服务器里上线,所以不存在跨域问题
- 若还是需要配置跨越可以:
-
ngnix:代理服务 原理就是和我们本地开发服务器做跨域相似
-
配置身份标记,设置好响应头内容使得浏览器可以识别:
- 配置好 "Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods"等字段
-
提示:文章到此结束,文章仅为个人学习记录,若有不足还请大家指出。