当前位置: 首页 > news >正文

跨域原因及解决方案

跨域(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':''},// 重写路径// 其他代理配置...}}}};
http://www.cnnetsun.cn/news/138688.html

相关文章:

  • 隧道代理技术解析:它为何成为数据安全传输的首选?
  • 网络安全入门必收藏!零基础小白5步实战指南,从零到黑客高手
  • 从地面站到太空节点,卫星Agent信号处理全流程拆解,不容错过
  • 大模型学习路线(2025最新)从零基础入门到精通,看完这一篇就够了
  • 【RT-DETR涨点改进】独家创新首发、Neck特征融合改进篇 | TGRS 2025顶刊 | RT-DETR引入HFFE高低频特征融合模块,增强多层次特征融合、噪声抑制,助力目标检测有效涨点
  • 【荐书】掌握LLM,全套方法就在这本书里
  • 【必藏】网络运维与网络安全运维的区别解析:就业前景与学习路线全攻略
  • FPGA实现Sobel边缘检测与中值滤波:基于灰度图像处理的探索
  • SC6D10170H-JSM 碳化硅肖特基二极管
  • 探索三相光伏并网仿真模型:从原理到实现
  • 引领测试创新:领导力在软件质量保障中的核心作用
  • 29、认证与虚拟专用网络协议配置及故障排除指南
  • 深度学习初学者指南
  • 基于PLC的蔬菜大棚温湿度环境控制系统设计
  • 基于RBF神经网络的车速时序预测
  • linux——进程状态
  • 推荐一个langchain开发工具包:langchain-dev-utils
  • 有序二叉树节点的删除
  • “即插即用”的智能升级:具身智能模块如何破解机器人产业化难题
  • AI驱动的芯片设计革命:当算法开始替代“老师傅”的经验
  • 基于深度学习的交通标志检测系统(YOLOv10+YOLO数据集+UI界面+Python项目源码+模型)
  • 基于深度学习的大豆检测系统(YOLOv10+YOLO数据集+UI界面+Python项目源码+模型)
  • 基于深度学习的苹果腐烂检测系统(YOLOv10+YOLO数据集+UI界面+Python项目源码+模型)
  • 基于深度学习的食物检测系统(YOLOv10+YOLO数据集+UI界面+Python项目源码+模型)
  • 基于深度学习的数字识别检测系统(YOLOv10+YOLO数据集+UI界面+Python项目源码+模型)
  • STM32定时器定时中断
  • 打破离散制造“内卷”:工业智能体(AI Agent)落地的五大核心原则
  • C语言 操作符 关系操作符 笔记
  • 2025年战略咨询在行业标准演进中的推动力
  • 【电商API接口】电商平台价格监控行业全景:数据驱动的定价革命