小白也能懂!跨域问题到底是啥,咋解决?

小白也能懂!跨域问题到底是啥,咋解决?

大家好呀!最近有朋友问我:"我做了个小网页,想拿别人网站的数据(比如天气 API),结果浏览器报错说'跨域了',这啥意思啊?" 今天就用大白话给大家讲明白 ------ 跨域问题到底是啥,以及怎么解决它。

一、先搞懂:啥是 "跨域"?

要理解 "跨域",得先知道一个词:同源

"同源" 就是说两个网址的「协议」「域名」「端口号」这三样必须完全一样!少一个一样都不行。

举个栗子,假设你的网页地址是 a.com:8080(协议是 http,域名是a.com,端口 8080),那下面这些情况就是「跨域」:

你的网址 要访问的网址 为啥跨域?
a.com:8080 a.com:8080 协议不一样(http≠https)
a.com:8080 b.com:8080 域名不一样(a.comb.com
a.com:8080 a.com:3000 端口不一样(8080≠3000)

简单说:只要两个网址不是 "同源",你从 A 网址去拿 B 网址的数据,浏览器就会拦着你,这就是跨域问题

二、为啥浏览器要 "拦着"?------ 同源策略

你可能会问:"浏览器为啥这么严?我就是想拿点数据而已啊!"

这其实是浏览器的一个安全规则,叫「同源策略」,目的是保护你的信息安全。

再举个栗子:你登录了淘宝(taobao.com),浏览器会存一个 "登录凭证"(cookie)。如果没有同源策略,随便一个小网站(bad.com)都能偷偷拿你淘宝的登录凭证,那你的账号不就危险了?

所以「同源策略」就像你家的门锁 ------ 只让 "自己人"(同源网址)进,不让 "外人"(跨域网址)随便碰你家东西(数据)。

三、3 个小白也能懂的解决办法

知道了啥是跨域、为啥有跨域,接下来就是重点:怎么解决?

下面给大家讲 3 个最常用、最简单的办法,不同场景选不同的就行~

办法 1:让后端 "开门"------ CORS(最推荐)

这是现在最常用的办法,核心是:让你要访问的后端(比如天气 API 的服务器)主动说 "允许你这个网址来拿数据"

怎么实现?其实不用前端操心,让后端在返回数据时,多带一个 "特殊头信息" 就行。

举个后端的简单例子(用 Node.js 写的,其他语言逻辑一样):

php 复制代码
// 后端代码( Node.js + Express )
const express = require('express');
const app = express();
// 关键:加这行代码,
app.use(cors({
  // 允许所有域名跨域访问
  origin:"*",
  // 允许所有 HTTP 方法跨域访问,这里默认是加了预检请求
  methods:["GET","POST","PUT","DELETE"],
  // 允许所有请求头跨域访问
  allowedHeaders:["Content-Type","Authorization"],
}))
// 后端接口:返回天气数据
app.get('/weather', (req, res) => {
  res.send({ city: '北京', temp: '25℃' }); // 给前端的数据
});
app.listen(3000);

前端不用改任何代码,直接正常发请求就行:

javascript 复制代码
// 前端代码(普通JS)
fetch('http://b.com:3000/weather') // 访问后端接口
  .then(res => res.json())
  .then(data => console.log(data)); // 成功拿到天气数据!

适用场景:你能联系到后端开发者(比如公司内部项目),让他们加这行配置。

办法 2:借 "script 标签" 的光 ------ JSONP(老项目常用)

有些老项目后端没法改,那可以用 JSONP。它的原理很有意思:浏览器的 script 标签不受同源策略限制(比如你能在自己网页里引百度的 JS 文件)。

实现步骤也很简单:

  1. 前端先定义一个 "回调函数"(用来接收数据);
  1. 用 script 标签去请求后端接口,并且把 "回调函数名" 传给后端;
  1. 后端返回一段 JS 代码,内容是 "调用这个回调函数,把数据当参数传进去"。

举个例子:

javascript 复制代码
// 1. 前端定义回调函数(拿到数据后要做的事)
function handleWeather(data) {
  console.log('拿到天气了:', data); // 比如打印数据
}
// 2. 用script标签请求后端接口,传回调函数名
const script = document.createElement('script');
// 后端接口地址 + ?callback=回调函数名
script.src = 'http://b.com:3000/weather?callback=handleWeather';
document.body.appendChild(script); // 插入页面,发起请求
// 3. 后端返回的内容会是:handleWeather({city:'北京', temp:'25℃'})
// 浏览器执行这段JS,就会调用我们定义的handleWeather,拿到数据!

后端代码(Node.js):

javascript 复制代码
app.get('/weather', (req, res) => {
  const callbackName = req.query.callback; // 拿到前端传的回调函数名
  const weatherData = { city: '北京', temp: '25℃' }; // 要返回的数据
  // 关键:返回"回调函数调用"的JS代码
  res.send(`${callbackName}(${JSON.stringify(weatherData)})`);
});

注意:JSONP 只能发 GET 请求,不能发 POST 请求,所以适合拿数据,不适合提交数据。

办法 3:前端自己 "搭个桥"------ 代理服务器(本地开发用)

如果你是本地开发(比如用 Vue/React 写项目),后端还没配置 CORS,那可以用 "代理服务器"。

原理很简单:浏览器有同源策略,但服务器之间没有! 所以我们让前端先把请求发给 "自己的代理服务器",再让代理服务器去请求后端,最后代理服务器把数据返回给前端。

以 Vue 项目为例,只需要改一下配置文件(vue.config.js):

java 复制代码
// vue.config.js 配置
module.exports = {
  devServer: {
    proxy: {
      // 只要前端请求以 /api 开头,就走代理
      '/api': {
        target: 'http://b.com:3000', // 后端接口的真实地址
        changeOrigin: true, // 告诉后端"我是从你允许的网址来的"(伪装)
        pathRewrite: {
          '^/api': '' // 把请求里的 /api 去掉(比如 /api/weather → /weather)
        }
      }
    }
  }
};

然后前端请求时,直接写 /api/weather 就行:

kotlin 复制代码
// 前端代码(Vue里)
this.$axios.get('/api/weather') // 看似请求自己的代理,实际会转发到后端
  .then(res => console.log(res.data));

适用场景:本地开发时临时用,不用麻烦后端改配置。

四、总结一下

  1. 跨域就是:浏览器不让不同 "源" 的网址互相拿数据,为了安全;
  1. 解决办法选哪个?
    • 能联系后端 → 用 CORS(最推荐);
    • 后端没法改,只需要 GET 数据 → 用 JSONP;
    • 本地开发临时用 → 用代理服务器。

其实跨域问题没那么难,关键是理解 "同源策略" 的初衷,然后根据场景选对方法~ 大家可以动手试试上面的例子,很快就能掌握啦!

相关推荐
用户90555842148058 小时前
Milvus源码分析:写流程
后端
易元8 小时前
Spring 应用记录(Bean的注册与注入机制)
spring boot·后端
Hooomeey8 小时前
深度解析线程与线程池:从 OS 调度内核到 Java 并发架构的演进逻辑
java·后端·架构
狂奔小菜鸡8 小时前
Day8 | Java 方法全解析
java·后端·java ee
豆浆Whisky8 小时前
Go编译器优化秘籍:性能提升的黄金参数详解|Go语言进阶(16)
后端·go
bcbnb8 小时前
Fiddler配置方法与使用教程:HTTP/HTTPS抓包分析、代理设置与调试技巧详解(开发者实战指南)
后端
Mos_x8 小时前
服务器公网IP、私网IP、弹性IP是什么?区别与应
java·后端
JavaArchJourney8 小时前
分布式锁方案详解
分布式·后端
用户99045017780098 小时前
程序员只懂技术还远远不够!不懂这点,你可能永远在敲代码
后端·面试