2025新时代 | 分析并解决企业跨域问题

本篇文章仅代表 个人观点

目录

问题分析

同源策略

满足条件

项目架构

案例分析

代码分享

前端

后端

后端配置解决跨域

注解方式

全局配置

现代企业实践

Nginx解决跨域

跨域常见问题集锦

安全建议


问题分析

同源策略

跨域问题的核心来源于浏览器的 同源策略(Same-Origin Policy) ,这是浏览器的一种安全机制,限制不同源的脚本或资源进行交互。在 前后端分离架构 的现代项目中,前端(如 React、Vue)和后端(如 Spring Boot、Node.js)通常部署在不同域名或端口下进行请求通信就会遇到问题。

满足条件

总之必须就得满足三个条件一致,就不会触发同源策略

  1. 协议 (http | https | file ....)
  2. IP (ipv4 | ipv6 | 域名 | 内网穿透 ....)
  3. 端口 (80 | 8080 | 8090 .....)

项目架构

案例分析

后面,我会出一期"关于多种请求方式"这个话题来讲!

项目架构:前后端分离

前端项目:live-server 搭建的临时静态页面,端口 8090

请求方式:fetch(替代了ajax)

后端项目:springboot 构建的临时控制层,端口 8080

前端获取用户输入的值后,JS 原生API工具 请求给后端 ,后端处理数据后,进行返回 ,但是因为端口号不一致,所以就被浏览器拦截了请求,

代码分享

前端

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        function go() {
            const number = document.getElementById('name').value;
            fetch("http://127.0.0.1:8080/hello?a="+number)
            .then(response => response.text())
            .then(data => console.log(data));
        }
    </script>
</head>
<body>
    <input type="text" name="a" id="name" placeholder="Number a">
    <button type="button" onclick="go()">go</button>
</body>
</html>

后端

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 后端的springboot构建方式 |
| 超简易SpringBoot工程构建与部署 ( 图解 - 零基础专属 ) <---这个是您想要的项目构建方式 |
| Springboot | 零基础快速搭建JWT简单登录案例(一) |
| SpringBoot构建项目后出现Connect timed out/Read timed out |
| 基于SpringBoot构造超简易QQ邮件服务发送(分离-图解-新手) |

java 复制代码
//Temp.java
package com.chen.www.demos;//这是包名,到时候智能提示会改掉的

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
//@CrossOrigin(origins = "*") 这是后续讲到的跨域注解
public class Temp {
    @GetMapping("/hello")
    public int hello(int a) {
        System.out.println("Hello !"+a);
        return a;
    }
}

后端配置解决跨域

注解方式

通过 @CrossOrigin 注解直接在 Controller 或方法上声明允许跨域

java 复制代码
@RestController
@CrossOrigin(
    origins = "https:/127.0.0.1:8090",  // 这里是允许谁通过
    allowedHeaders = "*",                 // 允许的请求头
    methods = {RequestMethod.GET, RequestMethod.POST} // 允许的 HTTP 方法
)
public class ApiController {
    // ...
}

全局配置

在配置类中定义全局跨域规则,适合微服务架构下的统一管理(Spring Security 或 WebMvcConfigurer)

java 复制代码
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("https:/127.0.0.1:8090")  // 这里是允许谁通过
                .allowedMethods("*")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

现代企业实践

  • API 网关统一处理 :在微服务架构中,通过 Kong、Spring Cloud Gateway 等网关组件集中配置跨域策略。

  • 云服务集成:使用 AWS API Gateway、Azure API Management 等云服务自动配置 CORS 规则。

Nginx解决跨域

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 安装教程 |
| Linux | 零基础Ubuntu安装部署 Nginx服务 |

通过 Nginx 将前端和后端请求代理到同一域名下,绕过浏览器同源策略:

java 复制代码
server {
    listen 8090;
    server_name https:/127.0.0.1:8090; # 这里是前端服务器

    location /api {
        proxy_pass https:/127.0.0.1:8080;  # 后端服务地址
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        # 添加 CORS 响应头
        add_header 'Access-Control-Allow-Origin' 'https:/127.0.0.1:8090';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
    }

    # 前端静态资源
    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}

跨域常见问题集锦

(认知 → 入门 → 新手 → 老手 → 企业实践 → 大佬)

Q0: 被拦截前,请求能修改数据吗?

A:0 是的,只是返回响应时,被浏览器拦截了。


Q1:为什么本地开发时前端访问后端接口会报跨域错误?
A1 :本地前端(如 localhost:3000)和后端(如 localhost:8080)端口不同,属于跨域。浏览器的同源策略会拦截 AJAX 请求的响应。
解决

  • 后端配置 @CrossOrigin(Spring Boot)或 CORS 头(Node.js)。

  • 前端开发环境代理(Webpack/Vite)。


Q2:后端已经配置了 @CrossOrigin,为什么还是跨域失败?
A2:常见原因:

  1. 未启用 allowCredentials :若请求带 Cookie/JWT,需配置 allowCredentials=true,且 allowedOrigins 不能为 *

  2. HTTP 方法或 Header 未允许 :如 PUTDELETE 或自定义 Header 需显式声明。

  3. Spring Security 拦截:需在 Security 配置中放行跨域。


Q3:JSONP 能解决跨域吗?为什么不推荐使用?
A3 :JSONP 通过 <script> 标签加载跨域脚本,仅支持 GET 请求。
缺点

  • 安全性差(易受 XSS 攻击)。

  • 无法处理错误和异步场景。

  • 已被 CORS 取代,现代项目不建议使用。


Q4:预检请求(Preflight)对性能有什么影响?如何优化?
A4

  • 影响:非简单请求(如带自定义 Header 的 POST)会先发 OPTIONS 请求,增加一次 RTT(往返延迟)。

  • 优化

    1. 后端设置 Access-Control-Max-Age 缓存预检结果(如 3600 秒)。

    2. 减少非必要自定义 Header。

    3. 合并请求,减少预检次数。


Q5:跨域请求携带 Cookie/JWT 时需要注意什么?
A5

  • 前端

    javascript 复制代码
    fetch(url, { 
      credentials: 'include' // 允许发送 Cookie
    });
  • 后端

    • 配置 allowCredentials=true

    • allowedOrigins 必须为具体域名(不能为 *)。

    • 设置 Access-Control-Expose-Headers: Authorization 以暴露 Token。


Q6:被拦截前,请求能修改数据吗?
A6

  • 简单请求(如 GET/POST):请求会到达服务器并执行操作(如插入数据库),但响应被浏览器拦截。

  • 预检请求(如 PUT/DELETE):OPTIONS 预检失败时,实际请求不会发送,数据不会被修改。


Q7:微服务架构下如何统一管理跨域配置?
A7

  • API 网关:通过 Kong、Spring Cloud Gateway 等网关集中配置 CORS 策略,避免每个服务重复配置。

  • 云服务:AWS API Gateway、Azure API Management 支持一键开启 CORS。

  • Kubernetes Ingress:在 Ingress 层添加 CORS 注解。

    bash 复制代码
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "https://web.example.com"

Q8:生产环境跨域配置与开发环境有何不同?
A8

  • 开发环境

    • 使用前端代理(如 Vite Proxy)或后端允许所有源(allowedOrigins: "*")。
  • 生产环境

    • 严格限制 allowedOrigins 为可信域名(如 https://web.example.com)。

    • 启用 HTTPS,配置 HSTS 防止协议降级攻击。

    • 通过 WAF(Web 应用防火墙)过滤恶意跨域请求。


Q9:如何监控和排查跨域问题?
A9

  1. 浏览器日志:通过开发者工具的 Console 和 Network 查看 CORS 错误和请求详情。

  2. 后端日志:检查 OPTIONS 和实际请求是否到达服务。

  3. APM 工具:使用 Datadog、New Relic 跟踪跨域请求链路。

  4. 安全扫描:使用 OWASP ZAP 检测不安全的 CORS 配置。


Q10:跨域场景下文件上传(如 Multipart)会触发预检吗?
A10

  • 会触发预检 :因为 Content-Type: multipart/form-data 属于非简单请求。

  • 优化方案

    1. 后端预检配置允许 Content-Type

    2. 分片上传改为简单请求(如 Base64 编码)。

安全建议

  • 精细化控制 :避免使用 allowedOrigins: "*",明确指定可信域名,严格限制来源。

  • JWT 鉴权 :跨域请求中通过 Authorization Header 传递 Token。

  • 性能优化:缓存预检请求,合并非简单操作。

  • 监控与日志:通过 APM 工具(如 Datadog、SkyWalking)追踪跨域请求异常。

  • 监控兜底:生产环境需监控跨域异常,防止配置错误导致服务不可用。

  • 架构选择

    • 小型项目:后端直接配置 CORS。

    • 中大型项目:通过网关或反向代理(Nginx)统一管理。


往期内容

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 基于SpringBoot构造超简易QQ邮件服务发送(分离-图解-新手)-CSDN博客 |
| 基于SpringBoot构造超简易QQ邮件服务发送 第二版-CSDN博客 |
| SpringBoo+Vue简单开发"任务管理系统"学生版(GTD+OKR简易测试版)_springboot + vue 控制任务流程的组件 |
| 热部署 | 解决SrpingBoot编译失败跟重复手动编译问题(新手图解)_springboot重新编译-CSDN博客 |

感谢阅读 | 更多内容尽在公棕号 wmcode

相关推荐
Goober Airy13 分钟前
JS:将JS对象格式化为php语法形式(完美支持无unicode编码匹配的正则)
开发语言·前端·javascript
一杯甜梦去冰全糖22 分钟前
CSS-Flex和Grid的区别
前端·css
gopher_looklook22 分钟前
深度讲解Go源码-sync.WaitGroup
后端·go·源码
ybq1951334543123 分钟前
javaEE-9.HTML入门
前端·java-ee·html
哟哟耶耶25 分钟前
css-根据不同后端返回值返回渲染不同的div样式以及公共组件设定
开发语言·前端·css
还是鼠鼠1 小时前
详细介绍:使用 Axios 上传图片文件
开发语言·前端·javascript·vscode·ajax·前端框架·bootstrap
还是鼠鼠1 小时前
使用 Axios ——个人信息修改
前端·javascript·css·vscode·ajax·前端框架·html5
傻小胖1 小时前
ES6 const 使用总结
前端·javascript·es6
Mengke1 小时前
以数字开头的 ID 在 querySelector 中的处理
前端·javascript·css
招风的黑耳1 小时前
Axure设计元件库分享——SpringUI Web端动态交互元件库
axure·web·元件库·动态交互