解决跨域资源共享(CORS)问题:PHP与JavaScript实战教程

解决跨域资源共享(cors)问题:php与javascript实战教程

本教程深入探讨了Web开发中常见的跨域资源共享(CORS)问题,特别是当JavaScript通过Fetch API请求PHP后端时遇到的挑战。文章详细解释了CORS机制、预检请求(OPTIONS)的处理,并提供了PHP服务器端配置CORS响应头的完整示例代码,指导开发者如何正确配置Access-Control-Allow-Origin、Access-Control-Allow-Methods等,以确保跨域请求成功。

1. 理解跨域资源共享(CORS)

跨域资源共享(Cross-Origin Resource Sharing, CORS)是一种浏览器安全机制,旨在允许网页从不同域(协议、域名或端口)请求资源。由于浏览器的同源策略(Same-Origin Policy)限制,默认情况下,JavaScript只能与同源的服务器进行交互。当前端应用(例如运行在 http://localhost:3000)尝试向不同源的后端API(例如 https://api.example.com)发送请求时,浏览器会触发CORS机制,并要求服务器明确授权该跨域请求。如果服务器未正确配置CORS响应头,浏览器将阻止请求,并抛出“Cross-Origin Request Blocked”错误。

2. CORS请求的类型与预检请求

CORS请求主要分为两种类型:

简单请求 (Simple Requests):满足特定条件的GET、HEAD或POST请求。这些请求不会触发CORS预检。条件包括:HTTP方法是GET、HEAD或POST。Content-Type 仅限于 application/x-www-form-urlencoded、multipart/form-data 或 text/plain。不使用自定义请求头。非简单请求 (Preflighted Requests):不满足简单请求条件的请求,例如使用了PUT、DELETE方法,或POST请求的Content-Type为application/json,或使用了自定义请求头。对于非简单请求,浏览器会在发送实际请求之前,自动发送一个HTTP OPTIONS方法请求到服务器,这就是所谓的“预检请求”(Preflight Request)。预检请求的目的是询问服务器是否允许实际的跨域请求。服务器必须响应OPTIONS请求,并包含适当的CORS响应头,告知浏览器允许哪些源、方法和头。如果预检成功,浏览器才会发送实际请求;否则,请求会被阻止。

3. 关键的CORS响应头

为了正确处理CORS请求,服务器需要在响应中包含一系列Access-Control-*头:

立即学习“PHP免费学习笔记(深入)”;

Vizard Vizard

AI驱动的视频编辑器

Vizard 101 查看详情 Vizard Access-Control-Allow-Origin: 必需。指定允许访问资源的来源。可以是一个具体的URL(例如 https://your-frontend-domain.com),也可以是通配符 *(表示允许任何来源,但在生产环境中应谨慎使用,因为它可能带来安全风险)。Access-Control-Allow-Methods: 必需。指定允许跨域访问的HTTP方法,例如 GET, POST, OPTIONS, PUT, DELETE。Access-Control-Allow-Headers: 必需。指定允许跨域请求携带的自定义请求头。如果请求中包含 Content-Type: application/json 或其他自定义头,服务器必须在此处列出它们。Access-Control-Allow-Credentials: 可选。如果前端需要发送Cookie或HTTP认证凭证(例如Authorization头),此头必须设置为 true。注意,当此头为 true 时,Access-Control-Allow-Origin 不能设置为 *,必须指定具体的来源。Access-Control-Max-Age: 可选。指定预检请求的结果可以被浏览器缓存多长时间(秒)。在此期间,浏览器无需再次发送OPTIONS预检请求。

4. PHP后端CORS配置实战

以下是一个PHP后端正确配置CORS以处理JavaScript跨域请求的示例。该示例着重于处理OPTIONS预检请求,并动态设置Access-Control-Allow-Origin。

 true, 'message' => '数据已成功接收');        echo json_encode($response);    }}?>

代码解释:

Access-Control-Allow-Origin: 优先检查 $_SERVER[‘HTTP_ORIGIN’] 来获取请求来源。在生产环境中,强烈建议您根据一个预定义的白名单来验证 HTTP_ORIGIN,而不是无条件地回显它或使用 *。Access-Control-Allow-Credentials: 如果前端请求需要携带认证信息(如Cookie或Authorization头),必须将其设置为 true。同时,Access-Control-Allow-Origin 不能为 *。Access-Control-Max-Age: 缓存预检请求的有效时间。在此时间内,浏览器将不再发送重复的OPTIONS请求。if ($_SERVER[‘REQUEST_METHOD’] == ‘OPTIONS’): 这是处理预检请求的关键。它会根据浏览器在 HTTP_ACCESS_CONTROL_REQUEST_METHOD 和 HTTP_ACCESS_CONTROL_REQUEST_HEADERS 中声明的需求,设置相应的 Access-Control-Allow-Methods 和 Access-Control-Allow-Headers。预检请求成功后,服务器应返回 204 No Content 状态码,并且必须使用 die() 终止脚本执行,以防止发送实际请求的响应内容。实际请求处理: 在 OPTIONS 块之后,才是处理 GET, POST 等实际请求的逻辑。此时,CORS头已经设置完毕,可以正常返回业务数据。

5. JavaScript客户端请求示例

前端JavaScript代码通常不需要为CORS做特殊处理,只需按照常规方式发送请求即可。浏览器会自动处理预检请求和CORS验证。

const url = 'https://opecart9349.000webhostapp.com/unzipper/opencart/index.php?route=customapi/test'; // 替换为你的PHP后端URLfetch(url, {  method: 'POST',  headers: {    'Content-Type': 'application/json', // 触发非简单请求,需要预检    // 'Authorization': 'Bearer your_token_here' // 如果需要发送认证头,服务器也需在Allow-Headers中允许  },  body: JSON.stringify({ name: 'John Doe', age: 30 }) // 示例数据})  .then(response => {    // 检查HTTP状态码,处理非2xx响应    if (!response.ok) {      throw new Error(`HTTP error! status: ${response.status}`);    }    return response.json();  })  .then(data => {    console.log('Success:', data);  })  .catch(error => {    console.error('Error:', error);  });

6. 注意事项与最佳实践

安全性优先:永远不要在生产环境中使用 Access-Control-Allow-Origin: *,除非你明确知道所有资源都应该对所有来源开放。这可能导致跨站请求伪造(CSRF)等安全漏洞。精确指定来源:始终将 Access-Control-Allow-Origin 设置为你的前端应用的具体域名(或一个域名白名单),例如 https://your-frontend-domain.com。正确处理 OPTIONS 请求:这是解决CORS问题的最常见痛点。确保你的服务器能够识别并正确响应OPTIONS请求,返回正确的CORS头,并立即终止脚本。使用 $_SERVER[‘HTTP_ORIGIN’]:在动态设置 Access-Control-Allow-Origin 时,优先使用 $_SERVER[‘HTTP_ORIGIN’] 来获取请求来源,而不是 $_SERVER[‘HTTP_REFERER’],因为 HTTP_ORIGIN 是专门为CORS设计的,而 HTTP_REFERER 可能不可靠或缺失。调试工具:利用浏览器开发者工具(通常是F12)的网络(Network)选项卡,检查请求和响应的HTTP头。特别关注OPTIONS请求的响应头,确保所有Access-Control-*头都正确设置。服务器配置:除了代码中的CORS头,有时Web服务器(如Apache或Nginx)的配置也可能影响CORS。确保它们没有覆盖或阻止你的PHP脚本设置的CORS头。

7. 总结

跨域资源共享(CORS)是Web开发中不可避免的一部分。正确理解CORS机制,特别是预检请求的作用,并按照本文提供的PHP后端配置示例,可以有效地解决“Cross-Origin Request Blocked”错误。核心在于服务器端要明确告知浏览器,哪些跨域请求是被允许的,以及允许哪些方法、头和来源。通过细致的配置和严谨的安全考量,可以确保您的Web应用在不同域之间安全、顺畅地通信。

以上就是解决跨域资源共享(CORS)问题:PHP与JavaScript实战教程的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/869776.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
2025年全画幅微单推荐:佳能R8,你的万元以内全画幅创作伙伴
上一篇 2025年11月28日 04:28:30
sql中如何进行拼接
下一篇 2025年11月28日 04:28:39

相关推荐

  • PHP 数组值比较与嵌套数组过滤教程

    本教程详细讲解如何在 PHP 中比较一个简单数组与一个复杂嵌套数组,并根据特定条件(如文件名匹配)过滤嵌套数组中的所有相关子数组。我们将通过识别非匹配项的索引,然后从所有子数组中移除这些项并重新索引,实现精确的数据筛选。 问题背景 在 php 开发中,我们经常会遇到需要处理结构复杂的数组数据。例如,…

    2026年9月21日
    100
  • 漫番漫画官方网页_ 漫番漫画在线访问入口

    漫番漫画官方网页入口为https://manwa.me,该平台汇聚多类型漫画资源,界面简洁、更新稳定,支持网页端流畅阅读;采用动态域名与镜像站点保障访问连续性,配备HTTPS加密提升安全性;提供个性化阅读设置、书架收藏及评论互动功能,优化用户体验。 漫番漫画官方网页入口地址在哪里?这是不少网友都关注…

    2026年9月21日
    200
  • Java集合框架在数据处理中的应用实例

    使用Set去重:通过LinkedHashSet去除标签重复并保持顺序;2. Map统计频次:利用HashMap统计单词出现次数;3. List结合Comparator排序:按年龄升序、姓名降序排列用户;4. 集合嵌套处理数据:用Map组织部门与员工列表。集合框架提升数据处理效率与代码可读性。 Jav…

    2026年9月21日
    000
  • Chrome浏览器怎么开启数据同步功能_Chrome浏览器跨设备数据同步设置教程

    首先登录Google账户启用Chrome同步功能,确保书签、历史记录、密码等数据跨设备一致;接着在设置中自定义同步内容类型以满足隐私需求;然后通过Google账户密钥或自定义密码加密同步数据,提升安全性;最后在新设备登录同一账户,自动接收已同步的浏览数据,实现无缝体验。 如果您希望在不同设备间无缝使…

    2026年9月21日
    000
  • 如何使用XGBoost训练AI大模型?优化机器学习模型的步骤

    XGBoost并非用于训练GPT类大模型,而是擅长处理结构化数据的高效梯度提升算法,其优势在于速度快、准确性高、支持并行计算、内置正则化与缺失值处理,适用于表格数据建模;通过分阶段超参数调优(如学习率、树深度、采样策略)、结合贝叶斯优化与交叉验证,并配合特征工程、数据预处理和集成学习等关键步骤,可显…

    2026年9月21日
    000
  • VSCode代码编辑器在线使用_VSCode网页版免安装直接进入编辑

    答案:无需安装即可在浏览器使用VSCode,主要方式包括GitHub Codespaces、Gitpod、StackBlitz、CodeSandbox和自托管code-server,适用于不同场景,如GitHub集成、前端开发或完全控制环境;但存在网络依赖、性能限制、插件兼容性、文件访问和安全等局限…

    2026年9月21日
    100
  • VSCode远程开发:配置容器与SSH连接的最佳实践解析

    使用VSCode远程开发提升效率,通过Remote-Containers和Remote-SSH实现环境标准化。1. 配置.devcontainer文件夹,用devcontainer.json定义容器环境,推荐自定义Dockerfile并预装工具;2. SSH连接需配置公钥认证、~/.ssh/conf…

    2026年9月21日
    100
  • 美图秀秀导出视频卡住 美图视频保存失败修复方案

    导出视频卡住或保存失败,通常和设备性能、软件状态或操作方式有关。直接强制退出再尝试是很多人会做的,但更有效的是先排查具体原因。 检查设备资源与软件状态 导出视频是个高负载任务,容易因资源不足中断。 关闭后台应用:尤其是浏览器、游戏或其他大型程序,释放内存和处理器资源。 确认存储空间:确保手机或电脑有…

    2026年9月21日
    000
  • 谷歌浏览器新建窗口无法继承上次会话标签如何解决

    谷歌浏览器新建窗口无法继承上次会话标签如何解决谷歌浏览器新建窗口无法继承上次会话标签如何解决谷歌浏览器新建窗口无法继承上次会话标签如何解决谷歌浏览器新建窗口无法继承上次会话标签如何解决

    答案是检查“启动时”设置并确保选择“继续上次会话”。具体操作为:打开谷歌浏览器设置→启动时→选择“继续上次会话”;新建窗口默认不继承标签页属正常设计,可通过拖拽标签或使用扩展解决;若问题仍存,可检查策略、禁用扩展或重置设置。 谷歌浏览器新建窗口无法继承上次会话的标签页,通常是因为设置未开启或某些配置…

    2026年9月21日 用户投稿
    000
  • 如何在Java中配置与数据库连接环境

    答案:Java中配置数据库连接需引入JDBC驱动,如MySQL在Maven中添加对应依赖;通过DriverManager或连接池(如HikariCP)获取Connection,使用try-with-resources管理资源;建议将连接参数存入properties文件,并处理常见问题如驱动加载、权限…

    2026年9月21日
    000
  • PHP错误日志怎么查看_PHP错误日志定位与查看方法

    要查看PHP错误日志,首先确定php.ini中error_log路径,若未设置则检查Web服务器(如Apache/Nginx)错误日志;确保log_errors=On、error_reporting合理配置,并通过tail、grep等工具分析日志,结合框架日志和系统日志(如syslog)全面定位问题…

    2026年9月21日
    200
  • 苹果为何把Apple ID改名为Apple Account

    苹果公司宣布将“Apple ID”更名为“Apple Account”,这一变化迅速引发热议。虽然只是名称上的调整,但其背后蕴含着深远的战略考量。 体现服务边界的扩展 随着苹果生态系统日益庞大,原有的“ID”一词已难以全面涵盖用户通过该账户所使用的广泛功能。如今,这一个账户不仅用于设备激活和App …

    2026年9月21日
    100
  • Java Executors类提供哪些线程池方法

    Executors类提供创建线程池的静态方法:newFixedThreadPool创建固定大小线程池,适用于稳定负载;newCachedThreadPool创建可缓存线程池,适合短期异步任务;newSingleThreadExecutor创建单线程池,保证任务顺序执行;newScheduledThr…

    2026年9月21日
    200
  • VSCode中怎么使用REM_VSCode移动端REM布局编写与换算教程

    答案:REM_VSCode插件可自动将像素转换为REM,需配置rootFontSize和precision,支持自动与手动转换,确保与html的font-size一致,配合media query适配不同屏幕,若插件异常可检查配置、重启或重装,替代工具有postcss-pxtorem、在线转换工具及浏…

    2026年9月21日
    100
  • UC浏览器如何开启省流模式_UC浏览器开启省流模式方法

    开启省流模式可减少UC浏览器流量消耗,通过设置菜单、首页快捷入口或搜索功能三种方式均可启用,系统会压缩网页内容以节省资源。 如果您在使用UC浏览器时希望减少数据流量消耗,尤其是在移动网络环境下,可以通过开启省流模式来优化网页加载方式。该功能会压缩页面内容,降低图片质量和资源体积,从而节省流量。 本文…

    2026年9月21日
    100
  • PHP PDO lastInsertId() 返回 0 的原因与解决方案

    在使用 PHP PDO 的 lastInsertId() 方法时,如果意外返回 0,通常是因为在执行 INSERT 语句后,又创建了一个新的数据库连接实例来调用 lastInsertId()。lastInsertId() 依赖于在同一数据库会话中获取最后插入的自增 ID。本文将深入解析此问题,并提供…

    2026年9月21日
    500
  • VSCode怎么新建ipynb文件_VSCode创建和编辑Jupyter笔记本文件教程

    答案:在VSCode中运行Jupyter笔记本需准备Python环境、安装Python扩展并确保安装ipykernel;通过命令面板或文件菜单新建笔记本,编辑时可添加代码或Markdown单元格,运行代码后结果实时显示;通过右上角内核选择器切换Python环境,推荐为不同项目配置独立虚拟环境以避免依…

    2026年9月21日
    200
  • UC浏览器下载速度慢怎么提升_UC浏览器下载速度提升方法

    开启极速模式、更换APN接入点、更改下载路径至内部存储、启用云端加速、清理缓存及切换网络环境可提升UC浏览器下载速度。 如果您在使用UC浏览器下载文件时遇到速度缓慢的问题,这可能是由于网络设置、缓存堆积或下载路径不佳所导致。以下是针对此问题的多种解决方法。 本文运行环境:小米14 Pro,Andro…

    2026年9月21日
    200
  • 夸克Ai搜索如何设置默认_夸克Ai搜索默认引擎更改

    首先在夸克APP中将默认搜索引擎设为AI引擎,再开启相关AI功能开关以启用AI搜索服务。具体步骤:1、打开夸克APP,点击右下角菜单进入设置;2、选择“通用”选项,点击“搜索引擎”;3、选择“AI引擎”或“夸克AI搜索”作为默认服务;4、返回主界面测试搜索关键词,确认AI结果是否展示;5、进入“AI…

    2026年9月21日
    400
  • iPhone 17 Pro如何关闭后台应用刷新

    关闭iPhone后台应用刷新可省电省流量,进入设置→通用→后台App刷新,关闭顶部总开关或单独关闭特定App,还能提升系统流畅度。 虽然目前还没有iPhone 17 Pro,但关闭后台应用刷新的方法在所有iPhone上都是一样的。你可以通过设置里的“通用”选项来管理这个功能,既能省电也能减少数据使用…

    2026年9月21日
    100

发表回复

登录后才能评论
关注微信