news 2026/6/15 7:09:30

跨域原因及解决方案

作者头像

张小明

前端开发工程师

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/6/13 22:50:35

DevOps理念

一、软件开发生命周期(SDLC)(一)概述Software Development Life Cycle(SDLC)是组织和实施软件开发管理的框架,定义系统工程师和开发人员在软件开发和维护中的工作阶段,主要包括需求收…

作者头像 李华
网站建设 2026/6/13 8:56:04

C语言初学者指南:掌握if语句,开启智能编程之旅

引言:为什么if语句如此重要? 作为一名C语言初学者,你刚刚迈入了编程世界中最激动人心的部分——让程序"思考"和"决策"。if语句是编程中的决策点,就像生活中的选择一样:如果下雨了,我就…

作者头像 李华
网站建设 2026/6/11 12:29:17

ECON-023100控制器

ECON-023100 控制器 产品应用领域:工业自动化:用于生产线、加工设备和机器人系统的集中控制与监控。能源管理:电力分配、发电机组和可再生能源系统的运行优化与调度。建筑自动化:智能楼宇管理系统,包括空调、照明、电梯…

作者头像 李华
网站建设 2026/6/13 20:07:24

PKS-60-0019电源模块

PKS-60-0019 电源模块 产品特点:高功率输出提供稳定的大功率直流输出,适合工业设备和高负载应用。宽输入电压范围可兼容不同电源环境,提高系统适应性和灵活性。高效率设计能量转换效率高,降低发热和能耗,支持长时间稳定…

作者头像 李华
网站建设 2026/6/15 6:44:29

飞牛 EVO2硬件预售来袭!快来看看是什么配置?!

今天真是好日子!2025年12月15日,飞牛EVO2开启预售,官方硬件终于来了吗?是的,它来了! 这个机型看起来确实颜值超高 首先咱们先来看外观和外部接口!看到这个图片,相信很多小伙伴都会有…

作者头像 李华
网站建设 2026/6/15 9:41:12

基于强化学习DDPG算法的ACC自适应巡航控制器设计

基于强化学习 DDPG 算法实现的acc 自适应巡航控制器设计 配有说明文档 基于simulink 中的强化学习工具箱,设计agent 的奖励函数,动作空间,状态空间,训练终止条件 设置领航车的速度和位移曲线,然后自车的加速度基于 acc…

作者头像 李华