本篇文章仅代表 个人观点
![](https://i-blog.csdnimg.cn/direct/bea0f0b5ee5b4708aef3aecdb97b8b40.jpeg)
目录
问题分析
同源策略
跨域问题的核心来源于浏览器的 同源策略(Same-Origin Policy) ,这是浏览器的一种安全机制,限制不同源的脚本或资源进行交互。在 前后端分离架构 的现代项目中,前端(如 React、Vue)和后端(如 Spring Boot、Node.js)通常部署在不同域名或端口下进行请求通信就会遇到问题。
满足条件
总之必须就得满足三个条件一致,就不会触发同源策略
- 协议 (http | https | file ....)
- IP (ipv4 | ipv6 | 域名 | 内网穿透 ....)
- 端口 (80 | 8080 | 8090 .....)
项目架构
案例分析
后面,我会出一期"关于多种请求方式"这个话题来讲!
项目架构:前后端分离
前端项目:live-server 搭建的临时静态页面,端口 8090
请求方式:fetch(替代了ajax)
后端项目:springboot 构建的临时控制层,端口 8080
前端获取用户输入的值后,JS 原生API工具 请求给后端 ,后端处理数据后,进行返回 ,但是因为端口号不一致,所以就被浏览器拦截了请求,
![](https://i-blog.csdnimg.cn/direct/2bd83fc37043425f8e4167101bcc2f30.png)
代码分享
前端
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:常见原因:
-
未启用
allowCredentials
:若请求带 Cookie/JWT,需配置allowCredentials=true
,且allowedOrigins
不能为*
。 -
HTTP 方法或 Header 未允许 :如
PUT
、DELETE
或自定义 Header 需显式声明。 -
Spring Security 拦截:需在 Security 配置中放行跨域。
Q3:JSONP 能解决跨域吗?为什么不推荐使用?
A3 :JSONP 通过 <script>
标签加载跨域脚本,仅支持 GET 请求。
缺点:
-
安全性差(易受 XSS 攻击)。
-
无法处理错误和异步场景。
-
已被 CORS 取代,现代项目不建议使用。
Q4:预检请求(Preflight)对性能有什么影响?如何优化?
A4:
-
影响:非简单请求(如带自定义 Header 的 POST)会先发 OPTIONS 请求,增加一次 RTT(往返延迟)。
-
优化:
-
后端设置
Access-Control-Max-Age
缓存预检结果(如3600
秒)。 -
减少非必要自定义 Header。
-
合并请求,减少预检次数。
-
Q5:跨域请求携带 Cookie/JWT 时需要注意什么?
A5:
-
前端:
javascriptfetch(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 注解。
bashnginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "https://web.example.com"
Q8:生产环境跨域配置与开发环境有何不同?
A8:
-
开发环境:
- 使用前端代理(如 Vite Proxy)或后端允许所有源(
allowedOrigins: "*"
)。
- 使用前端代理(如 Vite Proxy)或后端允许所有源(
-
生产环境:
-
严格限制
allowedOrigins
为可信域名(如https://web.example.com
)。 -
启用 HTTPS,配置 HSTS 防止协议降级攻击。
-
通过 WAF(Web 应用防火墙)过滤恶意跨域请求。
-
Q9:如何监控和排查跨域问题?
A9:
-
浏览器日志:通过开发者工具的 Console 和 Network 查看 CORS 错误和请求详情。
-
后端日志:检查 OPTIONS 和实际请求是否到达服务。
-
APM 工具:使用 Datadog、New Relic 跟踪跨域请求链路。
-
安全扫描:使用 OWASP ZAP 检测不安全的 CORS 配置。
Q10:跨域场景下文件上传(如 Multipart)会触发预检吗?
A10:
-
会触发预检 :因为
Content-Type: multipart/form-data
属于非简单请求。 -
优化方案:
-
后端预检配置允许
Content-Type
。 -
分片上传改为简单请求(如 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