如何在 Vue + PHP 项目中正确解决本地开发跨域(CORS)问题
前言本地开发时最常见的画面是Vue 跑在http://localhost:5173PHP 接口跑在http://127.0.0.1:8000浏览器控制台一片红字——has been blocked by CORS policy: No Access-Control-Allow-Origin header is present。于是有人在 PHP 里加了一行header(Access-Control-Allow-Origin: *)页面通了但带上 Cookie 之后又不行了或者接口一旦需要Authorization头预检请求preflight直接 405。跨域问题的麻烦之处在于它不是后端坏了而是浏览器按三个条件同时判断来源是否被允许、是否允许携带凭据、预检请求是否被正确应答。缺任何一个条件请求在浏览器层就被丢掉PHP 那边的日志里可能连一条访问记录都没有。本文先讲清浏览器到底在拦什么再给出 PHP 端可以照抄的响应头写法含预检提前返回然后说明携带 Cookie 时的额外条件最后给出本地开发更省事的方案Vite 代理。示例的最低 PHP 版本是 8.0。一、浏览器在拦什么简单请求与预检请求浏览器把跨域请求分成两类。判断依据是方法 请求头 Content-Type条件简单请求simple request触发预检方法GET/HEAD/POST其余方法PUT/DELETE/PATCH…Content-Typeapplication/x-www-form-urlencoded、multipart/form-data、text/plainapplication/json、text/xml等自定义头无带Authorization、X-Requested-With、自定义头额外动作直接发出读响应时校验 CORS 头先发一个OPTIONS预检也就是说用 axios/fetch 提交 JSON一定会触发预检。预检请求会带上Access-Control-Request-Method和Access-Control-Request-Headers服务器必须用Access-Control-Allow-Methods/Access-Control-Allow-Headers明确答上这些值浏览器才肯发真正的请求。一个容易被忽略的事实是请求其实已经发到服务器了简单请求尤其如此只是响应被浏览器拦下不给 JS 读取。所以后端日志里能看到请求前端却拿不到数据——这常常误导排查方向。二、PHP 端正确写法白名单 预检提前返回先明确原则不要回显任意 Origin也不要用*。维护一个白名单命中才回显并且加上Vary: Origin避免缓存层把 A 站点的响应发给 B 站点。?php // 最低版本PHP 8.0 declare(strict_types1); const ALLOWED_ORIGINS [ http://localhost:5173, http://127.0.0.1:5173, ]; $origin $_SERVER[HTTP_ORIGIN] ?? ; if ($origin ! in_array($origin, ALLOWED_ORIGINS, true)) { header(Access-Control-Allow-Origin: . $origin); header(Vary: Origin); header(Access-Control-Allow-Credentials: true); header(Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS); header(Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With); header(Access-Control-Max-Age: 600); } // 预检请求到此为止不要继续执行业务逻辑 if (($_SERVER[REQUEST_METHOD] ?? GET) OPTIONS) { http_response_code(204); exit; }三个细节必须注意Access-Control-Allow-Origin只能出现一次。如果 nginx 也加了同样的头浏览器会报The Access-Control-Allow-Origin header contains multiple values两个头同时存在等于没配。只在一处加。预检必须提前exit。如果OPTIONS请求继续往下走业务逻辑未登录时就会返回 401浏览器把预检判为失败真正的请求根本不会发出。Access-Control-Allow-Headers要覆盖前端真实发送的所有头。后端漏掉Authorization前端带 token 就直接失败。三、携带 Cookie 或凭据时的三个额外条件只要请求涉及 Cookie、Authorization头或fetch的credentials: include浏览器会切换到凭据模式规则会变得更严Access-Control-Allow-Origin不能是*必须是具体来源且要与当前页面来源完全一致协议、域名、端口一个都不能差http与https、localhost与127.0.0.1都算不同来源服务器必须返回Access-Control-Allow-Credentials: true前端必须显式开启fetch用credentials: includeaxios 用withCredentials: true或在默认配置里统一打开。Cookie 本身还受SameSite与Secure约束。SameSiteLax的 Cookie 不会随跨站请求发送如果前后端是不同站点且确实需要携带 Cookie需要SameSiteNone; Secure而Secure又要求 HTTPS。这也是为什么本地 HTTP 环境下带 Cookie 的跨域经常怎么配都不通——最省事的做法还是下面要说的代理方案。四、本地开发更推荐的做法用 Vite 开发代理跨域限制只在浏览器里存在。开发阶段完全可以让浏览器只跟 Vite 开发服务器打交道由它把/api请求转发给 PHP——对浏览器来说这是同源请求也就根本不存在 CORS。// vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { proxy: { /api: { target: http://127.0.0.1:8000, changeOrigin: true, }, }, }, })前端代码里把请求地址改成相对路径即可// 开发环境走 Vite 代理生产环境由 Nginx 反代到 PHP-FPM const api axios.create({ baseURL: /api, withCredentials: true }) const { data } await api.get(/products)后端可以用 PHP 内置服务器起一个最简环境php -S 127.0.0.1:8000 -t public代理方案的额外好处是Cookie 的域、SameSite行为与生产环境一致不用为了开发环境放宽安全设置。生产环境同样推荐同域 反向代理让 CORS 配置彻底消失只在确实需要开放给第三方站点时才配置白名单。常见坑点1.*和凭据同时出现❌header(Access-Control-Allow-Origin: *); header(Access-Control-Allow-Credentials: true);——浏览器直接拒绝报cannot be used with credentials且不管你怎么调前端都不通。 ✅ 回显白名单里命中的具体 Origin。2. 预检没有提前返回❌OPTIONS请求继续走鉴权中间件未登录返回 401/403——浏览器认定预检失败真正的POST压根没发出去排查看起来像后端没收到请求。 ✅if ($method OPTIONS) { http_response_code(204); exit; }放在所有鉴权逻辑之前。3. nginx 与 PHP 各加一份 CORS 头❌add_header Access-Control-Allow-Origin ...;写在 nginx 配置里PHP 里又加一次——响应出现两个同名头浏览器报contains multiple values。 ✅ 只在一个地方加如果历史配置改不掉可以在 PHP 里先header_remove(Access-Control-Allow-Origin)再自己设置。4. 白名单用包含判断❌if (str_contains($origin, localhost))放行——http://evil-localhost.attacker.com也能过。 ✅ 用in_array($origin, ALLOWED_ORIGINS, true)精确匹配比较时区分协议与端口。5.Allow-Headers漏项❌ 只写了Content-Type前端却发了Authorization或X-Requested-With——预检响应与请求头对不上报Request header field authorization is not allowed。 ✅ 把前端所有自定义头列全也可以调试期先回显Access-Control-Request-Headers的值稳定后再收紧成白名单。6.header()之前已有输出❌ 被include的文件开头有 BOM 或空行、调试时先echo了一句——header()报headers already sentCORS 头一个都没生效看起来就像配了没用。 ✅ 用无 BOM 的 UTF-8 保存?php前不留任何字符出口文件结尾不写?必要时在入口ob_start()兜底。7. 把 CORS 当成安全机制❌ 认为加了白名单就没人能调我的接口——CORS 只是浏览器的策略curl、Postman、服务端脚本完全不受影响。 ✅ 该做的鉴权、限流、CSRF 防护一个都不能少CORS 只是让浏览器愿意把响应交给你的前端代码。总结场景推荐做法关键点本地开发推荐Viteserver.proxy转发/api浏览器视角同源无 CORS必须跨域白名单回显 Origin不能用*加Vary: Origin带 Cookie具体 Origin Allow-Credentials: true前端还要withCredentials预检请求提前204返回不要走到鉴权逻辑生产环境同域反向代理让 CORS 配置彻底消失跨域问题的本质是三件事必须同时成立来源被允许、凭据被允许、预检被正确应答。开发阶段用 Vite 代理可以把这三件事一起绕开必须跨域时就按白名单回显、明确列出方法与会话头、预检提前返回这三条来做同时记住 CORS 从来不是安全边界。

相关新闻

超快激光加工机理与工艺实战:从飞秒脉冲到精密制造

超快激光加工机理与工艺实战:从飞秒脉冲到精密制造

在激光加工一线做工艺开发这些年,我越来越觉得,超快激光已经从实验室里的高精尖玩具,变成了微纳制造产线上的常规武器。切割心脏支架、给航空叶片钻冷却孔、在透明材料内部写光波导、给模具做微结构表面,这些场景里几乎都能看到飞…

2026/10/3 15:04:21 阅读更多 →
SBM-GML指数原理与Python实现:绿色全要素生产率测算及分解

SBM-GML指数原理与Python实现:绿色全要素生产率测算及分解

简介:本资源面向经济学、管理学及区域发展研究领域的学习者与科研人员,提供一套完整的全要素生产率测算工具,重点解决SBM-GML指数、ML指数及超效率SBM的Matlab实现问题,适合具备一定计量基础、希望快速上手效率评价与绿色生产率分…

2026/10/3 15:04:20 阅读更多 →
AI人才缺口超300万?真正缺的是能落地的工程化人才

AI人才缺口超300万?真正缺的是能落地的工程化人才

这些年被问到最多的一个问题,就是“AI行业人才缺口超过300万,我是不是该赶紧转过去”。这个说法本身没毛病,行业报告里反复出现,媒体也都在讲,但你只要在一线待过就会知道,这句话背后藏了很多没说出口的细节…

2026/10/3 15:04:20 阅读更多 →

最新新闻

Eigenface人脸识别:用PCA降维实现轻量级Python人脸识别系统

Eigenface人脸识别:用PCA降维实现轻量级Python人脸识别系统

简介:基于Python的Eigenface人脸识别课程设计包,面向需要完成人脸识别方向课程设计或毕业设计的高校学生,完整覆盖从人脸检测、特征提取、模型训练到识别验证的经典实现流程。包内共11个文件,包含5个Python源码脚本、模型配置json…

2026/10/3 15:39:17 阅读更多 →
全国矢量地图SHP处理指南:从RAR解压到坐标纠偏与发布

全国矢量地图SHP处理指南:从RAR解压到坐标纠偏与发布

简介:全国矢量地图shp格式压缩包面向GIS数据分析、城市规划、环境研究与交通管理等人员,提供了一套覆盖全国范围的基础地理数据,可满足行政区划、道路网络、水系、地貌及兴趣点等多种空间分析需求。包内共85个文件,以shp几何文件、…

2026/10/3 15:39:17 阅读更多 →
基于STM32的可穿戴多生理参数实时监测与预警系统实战解析

基于STM32的可穿戴多生理参数实时监测与预警系统实战解析

做可穿戴设备,尤其是一套能监测心率、血氧、体温这些生理参数的嵌入式系统时,我最大的感受是:难点从来不是传感器能不能读出数据,而是数据在真实场景下依然可靠。手指静止时MAX30102读出的心率很漂亮,一旦佩戴者走动、…

2026/10/3 15:39:17 阅读更多 →
OpenRig模拟驾驶舱DIY全攻略:铝型材框架组装与人体工程学调校

OpenRig模拟驾驶舱DIY全攻略:铝型材框架组装与人体工程学调校

玩模拟赛车的第一年,我一直是“办公桌挂载派”:方向盘夹在桌沿,踏板顶在墙角,整个人窝在椅子里开F1。开两圈还好,跑半小时勒芒耐力赛,手腕酸、后背僵、膝盖别着劲,成绩反而越来越差。后来一位玩…

2026/10/3 15:39:17 阅读更多 →
从零构建AI工程:数据管道、模型部署与踩坑实录

从零构建AI工程:数据管道、模型部署与踩坑实录

我刷到过不少AI工程类的教程,上来先教怎么装MLflow、怎么配Kubeflow、怎么搭一套线上Pipeline,跑个demo就结束了。但真正面对线上问题的时候,你多半还是抓瞎。我第一次看到ai-engineering-from-scratch这个项目名的时候,心里是偷着…

2026/10/3 15:38:16 阅读更多 →
Univer:面向AI Agent的开源办公应用底座

Univer:面向AI Agent的开源办公应用底座

1. 这不是又一个“AIOffice”玩具,而是一套能让AI真正坐进工位的办公应用底座 Univer这个名字,最近在开发者圈子里出现的频率越来越高,但很多人第一反应还是“是不是那个做在线表格的?”——其实完全不是。它不直接面向终端用户卖…

2026/10/3 15:38:16 阅读更多 →

日新闻

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南 【免费下载链接】ex-skill 前任 skill 项目地址: https://gitcode.com/gh_mirrors/exsk/ex-skill 前任.skill 是一个运行在 Claude Code 上的开源 Skill:导入微信、iMessage、短信、…

2026/10/3 0:00:27 阅读更多 →
45个经典Linux面试题:从命令到网络排障的完整考点解析

45个经典Linux面试题:从命令到网络排障的完整考点解析

刚开始带应届生的时候,我最头疼的就是他们拿着一摞Linux面试题背得滚瓜烂熟,一上机全露馅。后来自己从被面的人变成面别人的人,才慢慢摸清楚:Linux面试题考的根本不是答案本身,而是你面对一个不确定的系统问题时&#…

2026/10/3 0:01:28 阅读更多 →
SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

简介:本资源是一份面向SAP ABAP开发人员、生产计划专员及ERP实施顾问的实操型操作指南,聚焦SAP生产预留核心业务场景,系统解决物料预留创建、查询、校验与批量处理等高频问题。文档以结构化方式覆盖预留背景原理、OMC2编码规则、工厂级参数配…

2026/10/3 0:01:28 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 9:14:33 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 9:47:50 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/3 9:42:31 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →