什么是跨域?跨域怎么解决?跨域解决的是什么问题?

跨域定义:

"跨域",首先需要明确它的核心场景 ------浏览器端的安全限制 ,即浏览器为保护用户数据安全,默认禁止一个网站的 JavaScript 代码去请求另一个 "不同域" 的资源(如数据、图片、脚本等)。这种限制被称为 "同源策略"(Same-Origin Policy),而 "跨域" 就是 "突破同源策略、实现不同域间资源请求" 的行为。

一、什么是 "同源"?

"同源" 是浏览器判断是否允许资源请求的核心标准,需同时满足以下 3 个条件:

  1. 协议相同 :如都是 httphttpshttp://a.comhttps://a.com 不同源);
  2. 域名相同 :如都是 a.coma.comb.com 不同源,a.comsub.a.com 也不同源,后者是子域名);
  3. 端口相同 :如都是默认的 80(http)或 443(https)(a.com:8080a.com:80 不同源)。

只要有一个条件不满足,就属于 "不同域",此时浏览器会触发同源策略限制,阻止跨域请求。

二、为什么会有 "跨域问题"?

同源策略是浏览器的 "安全盾",目的是防止恶意网站窃取用户数据。举个例子:

  • 你登录了银行网站 https://bank.com(浏览器会保存银行的登录 Cookie);
  • 同时打开了一个恶意网站 https://evil.com
  • 如果没有同源策略,evil.com 的 JS 代码可以直接请求 bank.com 的 "查询余额" 接口,浏览器会自动带上你的银行 Cookie,导致余额被恶意获取。

正是同源策略的限制,evil.com 无法直接请求 bank.com 的资源,从而保护了你的数据安全。但这也带来了 "麻烦":合法的跨域需求无法实现 (如前端项目 http://localhost:8080 要请求后端 API http://api.example.com),这就是 "跨域问题" 的本质。

三、常见的跨域场景

日常开发中,以下情况都属于跨域,会触发浏览器限制:

四、如何解决跨域问题?

解决跨域的核心思路是 "让浏览器允许不同域的请求",常见方案有以下 3 种:

1. 后端配置 CORS(最常用、最标准)

CORS(Cross-Origin Resource Sharing,跨域资源共享)是 W3C 标准,本质是后端在响应头中添加允许跨域的规则,告诉浏览器 "这个请求是安全的,可以放行"。

复制代码
# 允许的请求源(* 表示允许所有源,生产环境建议指定具体域名,如 http://localhost:8080)
Access-Control-Allow-Origin: http://localhost:8080
# 允许的请求方法(如 GET、POST、PUT 等)
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
# 允许的请求头(如 Content-Type、Authorization 等)
Access-Control-Allow-Headers: Content-Type, Authorization

浏览器收到响应后,看到这些头信息,就会允许前端读取响应数据,从而解决跨域。

2. 前端配置代理(开发环境常用)

在开发阶段(如用 Vue、React 脚手架),可以通过 "代理服务器" 转发请求,绕过浏览器的同源策略限制。原理是:

  • 浏览器只限制 "前端直接请求后端",但不限制 "前端请求本地代理服务器"(因为同源,都是 localhost);
  • 代理服务器是后端服务,没有同源策略限制,可以自由请求目标后端接口;
  • 流程:前端 → 本地代理服务器 → 目标后端 → 本地代理服务器 → 前端。

以 Vue 为例,在 vue.config.js 中配置代理:

javascript 复制代码
module.exports = {
  devServer: {
    proxy: {
      // 匹配所有以 /api 开头的请求
      '/api': {
        target: 'http://api.example.com', // 目标后端地址
        changeOrigin: true, // 让代理服务器伪装成目标域名(解决后端可能的域名校验)
        pathRewrite: { '^/api': '' } // 去掉请求路径中的 /api(如 /api/user → /user)
      }
    }
  }
}

配置后,前端请求 /api/user,就会被代理到 http://api.example.com/user,避免跨域。

3. JSONP(兼容性好,但有局限)

JSONP 是早期的跨域方案,利用了 "<script> 标签没有同源策略限制" 的特性(如网页中引入其他域的 JS 脚本是允许的)。原理是:

  1. 前端定义一个回调函数 handleData(data),用于接收后端数据;
  2. 前端动态创建 <script> 标签,src 指向后端接口,并带上回调函数名:http://api.example.com/data?callback=handleData
  3. 后端返回 JS 代码:handleData({ "name": "张三" })
  4. 浏览器执行该 JS 代码,调用 handleData 函数,前端即可拿到数据。

局限 :只能支持 GET 请求(因为 <script> 标签只能发 GET 请求),且安全性较低(可能存在 XSS 风险),目前已逐渐被 CORS 取代。

五、针对前两种方法进行实战演示跨域解决

当你看到错误信息 has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource 时,这意味着浏览器因为跨域资源共享(CORS)策略阻止了你的请求。具体原因是:被请求的服务器没有在响应头中包含 Access-Control-Allow-Origin 字段,导致浏览器判定该跨域请求不安全,从而拒绝访问。


对于 后端使用 springboot(Java)

使用java(spring boot)进行开发进行演示可以有以下几种:

1.使用@CrossOrigin注解

复制代码
@CrossOrigin(origins = "http://localhost:5173"),替换成你的前端ip+端口即可

使用 @CrossOrigin 注解,对单个控制器或方法单独配置跨域,优先级高于全局配置:

2.全局跨域配置(推荐)

通过实现 WebMvcConfigurer 接口,配置全局跨域规则,对所有接口生效:

javascript 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")  // 对所有接口生效
                .allowedOrigins("http://localhost:8081", "https://example.com")  // 允许的前端域名,*表示允许所有(生产环境不推荐)
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")  // 允许的请求方法
                .allowedHeaders("*")  // 允许的请求头
                .exposedHeaders("token")  // 允许前端获取的响应头(默认只能获取简单响应头)
                .allowCredentials(true)  // 是否允许携带cookie(需配合具体域名,不能用*)
                .maxAge(3600);  // 预检请求的缓存时间(秒),减少重复预检请求
    }
}

关键参数说明

  • allowedOrigins:指定允许的前端域名,生产环境建议明确指定(如 https://www.xxx.com),避免使用 *(安全风险)。
  • allowCredentials(true):若前端需要携带 Cookie 或 Token 等认证信息,必须设置为 true,且 allowedOrigins 不能为 *
  • maxAge:预检请求(OPTIONS)的缓存时间,设置后浏览器在有效期内不会重复发送预检请求,优化性能。

对于前端使用Vue 项目

配置代理(vue.config.js)
javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue()],
    server:{
    proxy:{
       // 配置第一个代理规则:匹配所有以 /test 开头的请求
       '/sse':{
        target:"http://localhost:8081",// 目标服务器地址(后端接口的域名或IP)
        changeOrigin:true,// 开启代理:将请求头中的 host 改为目标服务器的 host
        rewrite:(path)=>path.replace(/^\/sse/, '') // 将路径中的 /test 替换为空
        // secure:false, // 当 target 是 https 时,是否验证 SSL 证书
       }
      //  配置第二个规则(如果需代理多个域名)
    },
  

六、关键注意点

  1. 跨域只存在于浏览器端后端之间的请求(如 Java 调用 Python 接口)没有同源策略限制,无需处理跨域;
  2. OPTIONS 预检请求 :当前端发送 "非简单请求"(如 POST 请求且 Content-Type 为 application/json、带自定义头 Authorization)时,浏览器会先发送一个 OPTIONS 请求(预检请求),询问后端 "是否允许该请求",后端需正确响应 OPTIONS 请求才能继续;
  3. Cookie 跨域 :默认情况下,跨域请求不会携带 Cookie,若需携带,需满足两个条件:
    • 后端响应头添加 Access-Control-Allow-Credentials: true
    • *前端请求时设置 withCredentials: true(如 Axios 中配置 axios.defaults.withCredentials = true),且后端 Access-Control-Allow-Origin 不能为 (需指定具体域名)。

总结:跨域是浏览器同源策略导致的安全限制,解决跨域的核心是 "让浏览器认可请求的安全性",推荐在生产环境用 CORS、开发环境用代理,JSONP 仅作为兼容性补充。

相关推荐
敲码图一乐2 小时前
流量安全——基于Sentinel实现限流,熔断,降级
java·开发语言·数据库
0xMinos2 小时前
Java 设计模式——单例模式
java·设计模式
zzywxc7873 小时前
AI赋能千行百业:金融、医疗、教育、制造业的落地实践与未来展望
java·人工智能·python·microsoft·金融·golang·prompt
一只学java的小汉堡3 小时前
Spring Boot 配置详解:从引导器到注解实战(初学者指南)
java·spring boot·后端
独自破碎E3 小时前
归并排序的递归和非递归实现
java·算法·排序算法
一叶飘零_sweeeet3 小时前
线程同步实战指南:从 bug 根源到锁优化的终极之路
java·线程·线程同步
失散134 小时前
分布式专题——25 深入理解网络通信和TCP、IP协议
java·分布式·网络协议·tcp/ip·架构
zz0723206 小时前
Java 集合体系 —— List 篇
java·list·集合体系
-雷阵雨-6 小时前
数据结构——LinkedList和链表
java·开发语言·数据结构·链表·intellij-idea