跨域请求:解决方案

一、跨域核心概念:同源策略与跨域定义

跨域问题的根源是浏览器的 同源策略(Same-Origin Policy),这是浏览器为保护用户数据安全而设置的核心安全限制。

1. 什么是 “同源”?

“同源” 指的是两个 URL 的 协议、域名、端口号 三者完全一致。只有满足同源条件,浏览器才允许 JS 脚本相互访问数据(如 AJAX 请求、操作 DOM 等)。

URL 示例与 http://www.example.com:8080/index.html 是否同源原因分析
http://www.example.com:8080/about.html协议(http)、域名、端口完全一致
https://www.example.com:8080/index.html协议不同(http vs https)
http://blog.example.com:8080/index.html域名不同(www vs blog,二级域名差异)
http://www.example.com:80/index.html端口不同(8080 vs 80)
http://www.example.org:8080/index.html主域名不同(example.com vs example.org)

2. 什么是 “跨域”?

当 JS 脚本尝试访问 非同源 的资源(如发起 AJAX 请求、获取非同源页面的 DOM)时,就会触发浏览器的同源策略限制,这种场景称为 “跨域”。

常见跨域场景:
  • 前端项目部署在 http://localhost:5500,请求后端接口 http://localhost:3000(端口不同)。
  • 本地开发时,请求线上接口(如前端 http://127.0.0.1 请求 https://api.taobao.com,域名不同)。

3. 同源策略的作用

同源策略并非 “限制”,而是 “保护”:

  • 防止恶意网站通过 JS 读取用户在其他网站的 Cookie(如登录状态)。
  • 防止恶意网站篡改非同源页面的 DOM,伪造用户操作。
  • 避免敏感数据(如用户信息、支付数据)被未授权的脚本窃取。

二、跨域解决方案:前端与后端配合实现

解决跨域的核心思路是 “绕过或允许” 同源策略限制,常见方案分为 前端主导(如 JSONP)、后端主导(如 CORS)和 代理转发(如 Nginx 代理)三类。以下重点讲解前端常用的 JSONP 和后端配置的 CORS。

1. 方案一:JSONP(前端主导,仅支持 GET 请求)

JSONP(JSON with Padding)是早期解决跨域的经典方案,利用 <script> 标签不受同源策略限制的特性实现跨域请求。

1.1 JSONP 原理
  • <script> 标签的 src 属性可以加载任意域名的资源(如 CDN 上的 JS 文件),浏览器不拦截。
  • 后端返回的不是纯 JSON 数据,而是 “回调函数名 ( JSON 数据)” 的 JS 代码。
  • 前端提前定义好回调函数,当 <script> 加载并执行后端返回的 JS 代码时,会自动调用回调函数,从而获取数据。
1.2 JSONP 实现步骤(前端 + 后端)
(1)前端实现(以 “淘宝商品搜索建议” 为例)

html

预览

<!-- 输入框:用户输入关键词 -->
<input type="text" id="searchInput" placeholder="输入商品关键词">
<button id="searchBtn">搜索</button>
<ul id="suggestList"></ul><script>
// 1. 提前定义回调函数:接收并处理后端返回的数据
function handleSuggest(data) {const suggestList = document.getElementById("suggestList");suggestList.innerHTML = ""; // 清空旧数据// 渲染搜索建议(淘宝接口返回的 data.result 是二维数组)data.result.forEach(item => {const li = document.createElement("li");li.innerText = item[0]; // item[0] 是商品名称suggestList.appendChild(li);});
}// 2. 点击按钮发起 JSONP 请求
document.getElementById("searchBtn").onclick = function() {const keyword = document.getElementById("searchInput").value;if (!keyword) return;// 3. 创建 <script> 标签,通过 src 发起跨域请求const script = document.createElement("script");// 淘宝开放接口:cb 参数指定回调函数名(必须与前端定义的一致)script.src = `http://suggest.taobao.com/sug?code=utf-8&q=${encodeURIComponent(keyword)}&callback=handleSuggest`;// 4. 将 <script> 插入页面,触发请求document.body.appendChild(script);// 5. 请求完成后移除 <script> 标签(避免页面冗余)script.onload = function() {document.body.removeChild(script);};
};
</script>
(2)后端实现(PHP 示例)

若后端是自建接口(如 PHP),需配合返回 “回调函数包裹的 JSON”:

php

<?php
// 1. 获取前端传递的回调函数名(参数名通常为 callback)
$callback = $_GET['callback'];// 2. 准备要返回的数据(模拟商品搜索建议)
$data = ["code" => 200,"msg" => "success","result" => [["iPhone 15", "10000+ 销量"],["iPhone 15 Pro", "5000+ 销量"],["iPhone 15 壳", "20000+ 销量"]]
];// 3. 转换为 JSON 字符串
$jsonData = json_encode($data);// 4. 输出:回调函数名( JSON 数据 )
echo $callback . "(" . $jsonData . ")";
// 最终输出:handleSuggest({"code":200,"msg":"success",...})
?>
1.3 JSONP 的优缺点
优点缺点
兼容性好(支持所有浏览器,包括 IE)仅支持 GET 请求(无法发送 POST/PUT/DELETE)
无需后端复杂配置(仅需返回特定格式)安全性低(可能遭受 XSS 攻击,需信任数据源)
前端实现简单无法捕获请求错误(如 404/500,<script> 加载失败无回调)

2. 方案二:CORS(后端主导,支持所有 HTTP 方法)

CORS(Cross-Origin Resource Sharing,跨域资源共享)是 W3C 标准,也是目前解决跨域的 主流方案。它通过后端在响应头中添加特定字段,明确告知浏览器 “允许该域名跨域访问”,从而绕过同源策略限制。

2.1 CORS 原理
  • 前端发起跨域请求时,浏览器会先发送一个 预检请求(OPTIONS 请求)(复杂请求,如 POST/PUT),询问后端 “是否允许当前域名访问”。
  • 后端通过响应头(如 Access-Control-Allow-Origin)告知浏览器允许的域名、方法、头部信息。
  • 浏览器验证响应头后,若符合条件,则允许前端接收数据;否则拦截请求。
2.2 CORS 实现步骤(后端配置 + 前端 AJAX)
(1)后端配置(以 PHP 为例)

只需在后端接口中添加 CORS 响应头即可,核心字段如下:

php

<?php
// 1. 允许的前端域名(* 表示允许所有域名,生产环境建议指定具体域名)
header("Access-Control-Allow-Origin: http://localhost:5500");// 2. 允许的请求方法(GET/POST/PUT/DELETE 等)
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");// 3. 允许的请求头(如 Content-Type、Authorization)
header("Access-Control-Allow-Headers: Content-Type");// 4. 允许前端携带 Cookie(需配合 withCredentials,生产环境慎用)
// header("Access-Control-Allow-Credentials: true");// 5. 处理预检请求(OPTIONS 请求):直接返回 204 状态码
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {http_response_code(204);exit;
}// 6. 业务逻辑:返回数据
$response = ["code" => 200,"msg" => "CORS 跨域请求成功","data" => ["username" => "张三", "age" => 20]
];
echo json_encode($response);
?>
(2)前端 AJAX 请求(与普通 AJAX 无差异)

html

预览

<button id="corsBtn">发起 CORS 请求</button>
<div id="corsResult"></div><script>
document.getElementById("corsBtn").onclick = function() {const xhr = new XMLHttpRequest();// 跨域请求:前端 http://localhost:5500 请求后端 http://localhost:3000xhr.open("POST", "http://localhost:3000/api/user", true);// 设置请求头(需与后端 Access-Control-Allow-Headers 匹配)xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");// 发送请求(POST 参数)xhr.send("username=张三");// 处理响应xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {const result = JSON.parse(xhr.responseText);document.getElementById("corsResult").innerText = JSON.stringify(result, null, 2);}};
};
</script>
2.3 CORS 的优缺点
优点缺点
支持所有 HTTP 方法(GET/POST/PUT/DELETE)后端需额外配置(但配置简单,一次配置全局生效)
安全性高(可精确控制允许的域名、方法)部分旧浏览器不支持(如 IE 8/9,需兼容时可用 JSONP)
支持携带 Cookie(需配置 withCredentials)复杂请求会多一次预检请求(OPTIONS),轻微影响性能

3. 其他跨域方案(补充)

除了 JSONP 和 CORS,实际开发中还可能用到以下方案:

  • Nginx 反向代理:前端请求本地 Nginx 服务器,Nginx 将请求转发到后端(因 Nginx 是服务器端,不受同源策略限制)。
  • PostMessage:用于两个非同源页面之间的通信(如 iframe 父子页面),通过 window.postMessage() 发送数据,window.addEventListener("message") 接收数据。
  • WebSocket:WebSocket 是全双工通信协议,一旦建立连接,不受同源策略限制(适合实时通信场景,如聊天、直播)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/100402.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/100402.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端形态与样式风格:从古典到现代的视觉语言演进

目录前端形态与样式风格&#xff1a;从古典到现代的视觉语言演进概述1. 前端形态的演进&#xff1a;四种核心范式1.1 古典范式&#xff1a;语义化HTML与CSS1.2 组件化范式&#xff1a;模块化与复用1.3 响应式范式&#xff1a;多端适配1.4 动态范式&#xff1a;状态驱动视图2. 样…

用户系统从0到1:登录、权限、积分一网打尽

&#x1f464; 用户系统从0到1&#xff1a;登录、权限、积分一网打尽 副标题&#xff1a;Flask-Login 多级权限 积分会员系统实战 项目原型&#xff1a;https://madechango.com 难度等级&#xff1a;⭐⭐⭐☆☆ 预计阅读时间&#xff1a;20分钟 &#x1f3af; 引子&#xff1…

Java 大视界 -- Java 大数据在智能安防视频监控系统中的视频内容理解与智能预警升级

Java 大视界 -- Java 大数据在智能安防视频监控系统中的视频内容理解与智能预警升级引言&#xff1a;正文&#xff1a;一、传统安防监控的 “三重困局”&#xff1a;看不全、看不懂、反应慢1.1 人工盯屏 “力不从心”1.1.1 摄像头密度与人力的矛盾1.1.2 录像调阅 “马后炮”1.2…

OpenHarmony包管理子系统核心源码深度解读:从BundleManager到AMS,彻底打通应用安装、卸载与沙箱机制全链路

目录 架构概览 核心组件详解 包安装流程分析 包卸载流程分析 包更新流程分析 包信息存储机制 Launcher界面管控 开机默认系统应用安装机制<

简单聊聊神经网络中的反向传播

参考文章&#xff1a; 一文弄懂神经网络中的反向传播法——BackPropagation - Charlotte77 - 博客园 反向传播求偏导原理简单理解_反向传播偏导-CSDN博客 这篇文章是笔者在读完上述两篇参考文章后的整理或者说按照自己的理解进行的一些补充&#xff0c;强烈推荐先阅读上述两篇文…

JSP自驾游管理系统46u2v--(程序+源码+数据库+调试部署+开发环境)

本系统&#xff08;程序源码数据库调试部署开发环境&#xff09;带论文文档1万字以上&#xff0c;文末可获取&#xff0c;系统界面在最后面。系统程序文件列表开题报告内容一、研究背景与意义 近年来&#xff0c;自驾游因自由度高、个性化强成为国内旅游市场增长最快的领域&…

通过 SQL 快速使用 OceanBase 向量检索学习笔记

背景 AI时代离不开向量数据库&#xff0c;向量数据库简单说就是在数据库中用多维向量存储某类事物的特征&#xff0c;通过公式计算各个向量在空间坐标系中的位置关系&#xff0c;以此来判断事物之间的相似性。相关基础概念如下: ● Embedding ● 距离/相似性度量 ○ Cosine dis…

PromptAD:首次引入提示学习,实现精准工业异常检测,1张正常样本即可超越现有方法

近年来&#xff0c;工业异常检测&#xff08;Anomaly Detection&#xff09;在智能制造、质量监控等领域扮演着越来越重要的角色。传统方法通常依赖大量正常样本进行训练&#xff0c;而在实际生产中&#xff0c;异常样本稀少甚至不存在&#xff0c;能否仅凭少量正常样本就实现精…

算法 --- 字符串

字符串 字符串算法题目主要处理文本的查找、匹配、比较、变换和统计问题&#xff0c;其核心特点是输入数据为字符序列&#xff0c;解题关键在于利用其连续性、前缀性、字典序等特性&#xff0c;并常借助哈希、自动机、指针滑动、动态规划等技巧高效处理。 详细分类型与适用场景…

SpringBoot中 Gzip 压缩的两种开启方式:GeoJSON 瘦身实战

目录 前言 一、GZIP压缩知识简介 1、什么是Gzip 2、Gzip特点 3、Gzip在GIS方面的应用 二、SpringBoot中开启Gzip的方式 1、在SpringBoot中开启Gzip的知识简介 2、SpringBoot中GeoJSON的实例 三、全局开启Gzip实现 1、实现原理 2、实现效果 四、局部约定配置 1、实现…

PPTist+cpolar:开源演示文稿的远程创作方案

文章目录前言【视频教程】1. 本地安装PPTist2. PPTist 使用介绍3. 安装Cpolar内网穿透4. 配置公网地址6. 配置固定公网地址前言 PPTist作为开源在线演示文稿工具&#xff0c;提供媲美PowerPoint的核心功能&#xff0c;支持多页面编辑、图表插入、音视频嵌入和动画效果设置。特…

服务注册/服务发现-Eureka

目的&#xff1a;解决微服务在调用远程服务时URL写死的问题注册中心服务提供者&#xff08;Server&#xff09;&#xff1a;一次业务中&#xff0c;被其他微服务调用的服务&#xff0c;也就是提供接口给其他微服务。服务消费者&#xff08;Client&#xff09;:一次业务中&#…

cuda stream

基本概念 cuda stream表示GPU的一个操作队列&#xff0c;操作在队列中按照一定的顺序执行&#xff0c;也可以向流中添加一定的操作如核函数的启动、内存的复制、事件的启动和结束等 一个流中的不同操作有着严格的顺序&#xff0c;但是不同流之间没有任何限制 cuda stream中排队…

数据结构:完全二叉树

完全二叉树 定义&#xff1a; 按层序遍历&#xff08;从上到下&#xff0c;从左到右&#xff09;填充节点。 除了最后一层外&#xff0c;其余各层必须全满。 最后一层的节点必须 连续靠左。 完全二叉树不一定是满二叉树。 满二叉树 (Full Binary Tree)&#xff1a;每个节点都有…

【Java初学基础】⭐Object()顶级父类与它的重要方法equals()

object类常见方法/*** native 方法&#xff0c;用于返回当前运行时对象的 Class 对象&#xff0c;使用了 final 关键字修饰&#xff0c;故不允许子类重写。*/ public final native Class<?> getClass() /*** native 方法&#xff0c;用于返回对象的哈希码&#xff0c;主…

用深度学习(LSTM)实现时间序列预测:从数据到闭环预测全解析

用深度学习&#xff08;LSTM&#xff09;实现时间序列预测&#xff1a;从数据到闭环预测全解析 时间序列预测是工业、金融、环境等领域的核心需求——小到预测设备温度波动&#xff0c;大到预测股价走势&#xff0c;都需要从历史数据中挖掘时序规律。长短期记忆网络&#xff08…

gpu-z功能介绍,安装与使用方法

GPU-Z 功能介绍、安装与使用方法 一、核心功能 硬件信息检测 识别显卡型号、制造商、核心架构&#xff08;如NVIDIA Ada Lovelace、AMD RDNA 3&#xff09;、制造工艺&#xff08;如5nm、7nm&#xff09;。显示显存类型&#xff08;GDDR6X、HBM2e&#xff09;、容量、带宽及显…

数据搬家后如何处理旧 iPhone

每年&#xff0c;苹果都会推出新款 iPhone&#xff0c;激发了人们升级到 iPhone 17、iPhone 17 Pro、iPhone 17 Pro Max 或 iPhone Air 等新机型的热情。但在获得新 iPhone 之前&#xff0c;有一件重要的事情要做&#xff1a;将数据从旧 iPhone 转移到新设备。虽然许多用户都能…

Java关键字深度解析(上)

这是一份全面的Java关键字实战指南 目录 1.数据类型关键字:内存布局与性能优化 1.1 基础类型的内存密码 byte-内存的极简主义者 int-Java世界的万能钥匙 long - 时间与ID的守护者 1.2 引用类型的架构设计 String-不是关键字但胜于关键字 2.访问修饰符:企业级权限控制 …

C语言深度解析:指针数组与数组指针的区别与应用

目录 1 引言&#xff1a;从名字理解本质区别 2 指针数组&#xff1a;灵活管理多个指针 2.1 基本概念与声明方式 2.2 内存布局与特性 2.3 典型应用场景&#xff1a;字符串数组与多维度数据管理 2.3.1 静态分配示例&#xff1a;字符串数组 2.3.2 动态分配示例&#xff1a;…