news 2026/2/8 18:26:22

跨域原因及解决方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
跨域原因及解决方案

跨域(CORS)原因及解决方案


文章目录

  • 跨域(CORS)原因及解决方案
    • 什么是跨域?
      • 浏览器的同源策略
      • 什么是跨域?
    • 如何解决跨域
      • JSONP(比较老的方法,不推荐)
      • CORS (服务器端设置)
      • 浏览器跨域配置(开发阶段,测试使用)
      • webpack/vite 等工程化工具中配置

什么是跨域?

浏览器的同源策略

浏览器有一个重要的安全机制,叫 同源策略(Same-Origin Policy)。它的意思是:浏览器只允许网页向和自己“同源”的地址发送请求,否则就拦截。
同源的定义是:
协议(http/ https)、域名(或 IP)、端口号 三者完全相同。
假设你的网页地址是:

http://localhost:3000/index.html

目标地址:

目标地址是否同源原因
http://localhost:3000/api/data✅同源协议、域名、端口号都一样
https://localhost:3000/api/data❌不同源协议不同(https 🆚 http)
http://127.0.0.1:3000/api/data❌不同源域名不同(localhost 🆚 127.0.0.1)

什么是跨域?

当你访问一个不同源的接口时,浏览器会因为同源策略阻止这个请求,这就是跨域。
通常控制台会出现这样的错误:

如何解决跨域

JSONP(比较老的方法,不推荐)

解决方法:

  1. 浏览器生成一个script元素,访问数据接口
  2. 服务器响应一段js代码,调用某个函数,并把响应数据传入

前端代码:

functionjsonp(url){constscript=document.createElement("script");script.src=url;// 为了不影响页面,script加载过后,将其移除script.addEventListener("load",()=>{script.remove();)}jsonp("请求的url地址");// 服务器返回的js函数functioncallback(data){console.log(data);}

服务器端代码:

router.get("/",async(req,res)=>{constresult=awaitstuServ.getStudents();res.status(200).send(getResult(result));// jsonp 实现跨域// 首先将 content-type的值设置为 “application/javascript”// 修改返回的数据,将数据放入到callback函数中res.header("content-type","application/javascript").send(`callback(${JSON.stringify(result)})`);});

JSONP的问题:

  • 会打乱服务器的消息格式:jsonp要求服务器响应js代码,但是在非跨域情况下,服务器又需要响应一个正常的json合适。
  • 只能完成GET请求:浏览器的script标签发出的请求,只能是get请求。

CORS (服务器端设置)

CORS是基于http1.1的一种跨域解决方案,它的全称是Cross-Origin Resource Sharing,跨域资源共享。
总体思路:如果浏览器要跨域访问服务器资源,需要获得服务器的允许。

三种不同的交互模式:

  • 简单请求

    • 需要同时满足的条件:
      1. 请求方法属于:get,post, head 中的一种
      2. 请求头仅包含安全的字段,常见安全字段如下:
        • Accept
        • Accept-language
        • Content-Type
        • Content-language
        • DPR
        • DownLink
        • Save-Data
        • Viewport-Width
        • Width
      3. 请求头如果包含 Content-Type,值只能为:
        • text/plain
        • multipart/form-data
        • application/x-www-form-urlencoded
    • 当浏览器判定某个ajax请求为简单请求时:
      1. 会在请求头中自动添加Origin字段,告诉服务器是哪个源地址在跨域请求

      2. 服务器响应头中应该包含Access-Control-Allow-Origin,允许跨域请求

        代码实现:

        constallowOrigins=["origin1","origin2",...];if("origin"inreq.headers&&allowOrigins.includes(req.headers.origin)){res.header("access-control-allow-origin",req.headers.origin);}
  • 需要预检的请求
    若浏览器判定ajax请求不是一个简单的请求,就会按照下面的流程进行:

    1. 浏览器发送预检请求(OPTIONS)询问服务器是否允许

    2. 服务器允许

    3. 浏览器发送真实请求

    4. 服务器完成真实响应
      例如:
      有一个需要预检的跨域请求:

      fetch("http://myRequest.com/api/test",{method:"POST",header:{"Content-Type":"application/json",a:"a",b:"b"},body:JSON.stringify({name:"abc",age:18})}).then(res=>res.json()).then(data=>console.log(data));

      此时浏览器会发送一个预检请求,询问服务器是否允许:

      预检请求有以下特征:

      • 请求方法为OPTIONS
      • 没有请求体
      • 请求头中包含
        • Origin:请求的源,和简单请求的含义一致
        • Access-Control-Request-Method:后续的真实请求将使用的请求方法
        • Access-Control-Request-Headers:后续的真实请求会改动的请求头

      若服务器允许,需要在请求头中添加:

      • Access-Control-Allow-Method: 允许的后续真实请求
      • Access-Control-Allow-Headers: 允许改动的请求头
      • Access-Control-Allow-Origin:允许的源
      • Access-Control-Max-Age:告诉浏览器,多少秒内,对于同样的请求源、方法、头,都不需要再发送预检请求了

      示例代码:

      constallowOrigins=["origin1","origin2",...];if(req.method==="OPTIONS"){res.header("Access-Control-Allow-Methods",req.header("access-control-request-method"));res.header("Access-Control-Allow-Headers",req.header("access-control-request-headers"));}if("origin"inreq.headers&&allowOrigins.includes(req.headers.origin)){res.header("access-control-allow-origin",req.headers.origin);}
  • 附带身份凭证的请求
    有一些场景,需要请求携带cookie,只需要在响应头中添加:Access-Control-Allow-Credentials: true即可。
    对于一个附带身份凭证的请求,若服务器没有明确告知,浏览器仍然视为跨域被拒绝。
    note:
    对于跨域请求,nodejs中可以使用 cors库来实现,也可以自己封装跨域的中间件。

浏览器跨域配置(开发阶段,测试使用)

谷歌浏览器为例:
1. 新建目录(如C:\MyChromeDevUserData)。‌‌
2. 右键快捷方式→属性→在“目标”字段末尾添加 --disable-web-security --user-data-dir=C:\MyChromeDevUserData(注意参数前有空格)。‌‌
若原目标值带引号,参数需加在引号外。‌‌

webpack/vite 等工程化工具中配置

module.exports={// 其他配置...devServer:{// 其他devServer配置...proxy:{'/api':{target:'http://example.com',// 目标服务器地址changeOrigin:true,// 是否改变源地址pathRewrite:{'^/api':''},// 重写路径// 其他代理配置...}}}};
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/8 18:08:14

工业元宇宙Agent渲染优化全攻略(性能提升90%实战案例)

第一章:工业元宇宙Agent渲染技术概述工业元宇宙正逐步成为智能制造、数字孪生与虚拟协作的核心平台,其中Agent作为具备感知、决策与交互能力的智能实体,其可视化渲染技术直接影响系统的沉浸感与实时性。为了实现高保真、低延迟的视觉呈现&…

作者头像 李华
网站建设 2026/2/8 11:03:57

为什么顶尖医院都在部署隐私计算?医疗 Agent 的未来已来

第一章:医疗 Agent 的隐私保护在医疗人工智能系统中,Agent 作为核心交互与决策单元,频繁处理患者健康记录、诊断数据和治疗方案等敏感信息。因此,确保其在整个生命周期中的隐私保护能力至关重要。隐私泄露不仅违反法律法规如《个人…

作者头像 李华
网站建设 2026/2/5 14:33:41

为什么你的Agent在元宇宙中“卡顿”?深度剖析交互逻辑底层架构

第一章:元宇宙 Agent 的交互逻辑在元宇宙环境中,Agent(智能体)作为用户代理或自主实体,其交互逻辑构成了虚拟世界动态行为的核心。Agent 不仅需要感知环境变化,还必须基于规则或学习模型做出响应&#xff0…

作者头像 李华
网站建设 2026/2/4 5:17:32

智能施肥Agent实战指南(从数据采集到模型部署):打造高效种植闭环系统

第一章:智能施肥Agent的核心价值与系统架构 智能施肥Agent作为现代农业智能化转型的关键组件,致力于通过数据驱动的方式优化农田养分管理。该系统融合传感器网络、作物生长模型与人工智能算法,实现对土壤肥力、作物需求及环境变化的动态感知与…

作者头像 李华
网站建设 2026/2/7 2:47:28

660-078399-001发电机模块

660-078399-001 发电机模块的产品应用领域可以更详细地列为:工业电力系统:大型发电厂、工业园区的主发电或备用电源。船舶动力系统:商用船舶、军用舰艇及潜艇的船载发电和能量管理。铁路运输:火车、电动车组的车载电源及牵引辅助系…

作者头像 李华
网站建设 2026/2/5 9:47:06

MD500E全套开发方案:打开电机控制新世界的钥匙

MD500E全套开发方案,代码方案和解析文档原理图仿真资料。 包含: pmsm的foc控制算法,电阻、电感、弱磁控制算法,无感FOC控制算法,电流环自整定算法,磁链观测器算法磁链等参数的辩识算法,死区补偿…

作者头像 李华