项目实战5:跨域问题

42 阅读6分钟

请求deepseek模型就没有跨域问题,其他的flux就有,我不知道,于是我开始思考,虽然前端变化很快,迭代之下会出来很多新东西,让后人学习的时候不需要去了解那些底层的东西,但是这样真的好吗,直接上手一个框架,上来就是前后端,跨域问题直接给出模版让你解决,是的,这很方便,但是这也导致了一个问题,好像一些流程都不清晰,一直在懵懂里面过来,遇到问题就去看前人怎么解决,虽然说可以少走弯路,但是也让我们变得懈怠了,还是要清楚一点基本流程的;

所以,来和我一起跟着一个个的问题,找到对应的答案吧!

鸡哥告诉我,其实跨不跨域都取决你访问的那个服务器支不支持跨域,那么怎么知道一个api支不支持cors呢?

✅ 支持CORS的响应头: Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Authorization

❌ 不支持CORS: 没有这些响应头,或者浏览器控制台报错: "CORS policy: No 'Access-Control-Allow-Origin' header"

但是其实,如果跨域问题出现,你是看不到响应请求头的,这个我们后面讨论;

先来解决几个我特别疑惑的事情:

为什么前端放到使用密钥直接调用ai会比用服务器调用ai要危险呢?

前端代码被查看:

方法1:查看源代码

  • 右键 → 查看页面源代码
  • 或按 F12 → Sources 标签页,即使压缩混淆,API密钥仍然可见,这是因为编译后的代码其实是不会动静态变量的,所以很容易被看见;

方法2:查看网络请求

  • F12 → Network → 看到所有请求的完整信息,包括请求头

后端代码的特点:

**服务器端执行** - 代码在服务器上运行,用户看不到

**环境变量** - 密钥存储在服务器环境变量中

**访问控制** - 可以添加身份验证、限流等安全措施

这就像把钥匙放在家里(后端)vs 把钥匙给每个路人(前端)的区别!

但是生产环境前端也是被打包到了云服务器啊,为什么会出现在浏览器呢?

这就混淆了前端部署前端执行的概念:

前端代码的执行流程

1. 部署阶段(在服务器)

# 您的操作:打包并部署到云服务器
npm run build
# 生成 dist/ 文件夹
# 上传到云服务器的 /var/www/html/

2. 用户访问时发生了什么?

步骤1:用户打开浏览器访问您的网站

用户输入:https://yoursite.com

步骤2:服务器返回静态文件

云服务器 → 用户浏览器
发送:index.html, app.js, style.css 等文件

步骤3:关键点 - 代码在用户浏览器中执行!

// 这些代码现在运行在用户的电脑上!
const headers = {
  Authorization: `Bearer 
  sk-637626fc3eee4182808f199703bba004`
};

让我们看看用户如何查看"生产环境"代码:

// /assets/index-abc123.js 内容(即使压缩了)
const t="Bearer sk-637626fc3eee4182808f199703bba004";
// API密钥仍然清晰可见!

我使用vite代理到服务器,解决跨域问题,这些都是什么意思呢?

rewrite: (path) => path.replace(/^/api/, '') 这是 路径重写 功能:

// 浏览器请求:/api/v1/flux-dev
// 经过 rewrite 处理后:/v1/flux-dev
// 最终请求:https://api.bfl.ml/v1/flux-dev

为什么需要重写?

  • 浏览器请求: /api/v1/flux-dev
  • 但目标服务器的真实路径是: /v1/flux-dev
  • 所以需要去掉前缀 /api

是这个前端代理vite是作为一个什么,不是说只有后端可以代理吗?

Vite 在开发模式下实际上是一个 Node.js 服务器 ,它不仅仅是一个简单的前端构建工具。当你运行 npm run dev 时,Vite 会启动一个完整的 HTTP 服务器来:

服务静态文件 :提供你的 HTML、CSS、JS 等前端资源 处理模块热更新 :实现 HMR (Hot Module Replacement) 充当代理服务器 :转发 API 请求到其他服务器

也就是说,承载前端,也有着后端,这就是为什么它和前端可以同端口,因为他们本来就是一个服务啊;

代理的工作流程

  1. 浏览器向 http://localhost:5173/api/v1/flux-dev 发送请求
  2. Vite 服务器接收到这个请求
  3. Vite 根据配置将请求转发到 api.bfl.ml/v1/flux-dev
  4. 目标服务器返回响应给 Vite
  5. Vite 将响应转发给浏览器

CORS 是浏览器的安全策略,它阻止:

但不会阻止:

生产环境怎么办?

在生产环境中,你需要:

  • 真正的后端服务器 来处理代理
  • 或者配置 Nginx 等反向代理
  • 或者让 API 服务器支持 CORS

现在明白了吗?Vite 在开发时充当了一个"临时后端"的角色!

但是vite本身和浏览器不也应该有同源限制吗?

同源策略(Same-Origin Policy)是浏览器的安全机制 ,不是 HTTP 协议本身的限制。

浏览器中的 JavaScript:

// ❌ 这会被 CORS 阻止
fetch('https://api.bfl.ml/v1/flux-dev') 
  • 受同源策略限制
  • 需要目标服务器返回正确的 CORS 头 服务器之间的通信:
// ✅ Node.js 服务器可以自由请求任何 URL
const response = await fetch('https://api.
bfl.ml/v1/flux-dev')
  • 没有同源策略限制

既然vite不需要解决同源策略,那为什么在代理的时候还要用changeOrigin: true?

很好的问题! changeOrigin: true 确实不是为了解决同源策略,而是为了解决另一个问题: Host 头验证 。

问题场景

很多服务器会检查请求的 Host 头来验证请求来源,拒绝"可疑"的请求。

不设置 changeOrigin 时:

GET /v1/flux-dev HTTP/1.1
Host: localhost:5173          ← 这是 Vite 
服务器的地址
User-Agent: ...

目标服务器 api.bfl.ml 收到请求后:

  • 看到 Host: localhost:5173
  • 心想:"咦?你说你要访问我,但 Host 头是 localhost?可疑!"
  • 可能返回 400/403 错误

设置 changeOrigin: true 后:

GET /v1/flux-dev HTTP/1.1
Host: api.bfl.ml              ← 自动改为目
标服务器地址
User-Agent: ...

目标服务器收到请求:

  • 看到 Host: api.bfl.ml
  • "嗯,正常请求,处理!"

到此为止,就告一段落啦,还有啥问题赞评论区一起讨论学习吧!