news 2026/4/16 17:06:26

跨域原因及解决方案

作者头像

张小明

前端开发工程师

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/4/16 9:21:31

【必收藏】大模型学习全攻略:从小白到AI工程师的进阶之路

记得曾经有人说过这样一个俗语:三百六十行,行行转IT。 或许听到这个话的时候会觉得是一句玩笑话,但是浏览到网络上一些关于就业的文章,就能够明白这句话的真正意义所在。随着互联网的发展,越来越多人选择,…

作者头像 李华
网站建设 2026/4/16 14:32:12

为什么你的物流Agent总是超时?:基于百万级订单验证的7大调优技巧

第一章:物流运输 Agent 的时效保证在现代物流系统中,运输时效是衡量服务质量的核心指标之一。物流运输 Agent 作为智能调度与路径优化的关键组件,通过实时数据感知、动态资源调配和预测性决策,显著提升了运输过程的可控性与时效稳…

作者头像 李华
网站建设 2026/4/16 12:44:26

疾控实验室信息系统选型指南:需求分析与实践路径

一、疾控实验室信息系统需求分析1.1 功能需求疾控实验室信息系统(LIMS)的核心功能需求需覆盖日常检测与应急响应两大场景。在日常检测流程中,系统需支持样本接收、检测任务分配、结果录入与审核、报告生成等全流程自动化管理,实现…

作者头像 李华
网站建设 2026/4/16 14:31:39

探索第三方 WINCC 报表控件:强大功能与便捷使用

第三方WINCC报表控件 经典WINCC,博途WINCC用的报表控件,可以根据归档记录查询年月日时分秒报表,计算出最大值最小值平均值总和,可以导出表格,无使用限制,可以在不同电脑不同项目上永久使用,内有…

作者头像 李华