报错信息
前端项目发送请求给后端时报错:
如上图所示,由 http://localhost:8082 向 http://localhost:8088/user/list 发起 AJAX 请求,由于端口不同,产生了跨域问题。
什么是跨域?
跨域是指浏览器的同源策略限制下,一个域(网站)下的脚本试图去请求另一个域(网站)的资源。同源策略是浏览器的一种安全机制,用于限制一个源的文档或脚本如何与另一个源的资源进行交互,它要求协议、域名和端口都相同,如果这三个中的任何一个不同,就会产生跨域问题。
1. 同源策略的概念
- 同源策略规定,只有来自同一源的脚本才能访问当前文档的某些属性和方法,以及与当前文档进行交互。例如,一个运行在
http://example.com
的网页中的 JavaScript 脚本,默认情况下不能访问http://another.com
上的资源,这就是同源策略在起作用。同源策略有助于防止恶意网站窃取用户数据或进行其他安全威胁行为。
2. 跨域的具体情况
- 协议不同:如
http://
和https://
是不同的协议,即使域名和端口相同,从http://example.com
向https://example.com
发送请求就属于跨域。 - 域名不同:这是最常见的跨域情况,比如从
http://example.com
向http://other.com
发送请求就是跨域。即使是二级域名不同也算跨域,例如http://sub.example.com
向http://main.example.com
发送请求(在没有特殊配置的情况下)属于跨域。 - 端口不同:如果两个资源的协议和域名相同,但端口不同,也属于跨域。例如,
http://example.com:8080
向http://example.com:3000
发送请求就是跨域。
3. 跨域对 Web 开发的影响
- 在前端分离的开发模式中,前端应用通常运行在一个域(如
http://localhost:8080
),而后端 API 可能运行在另一个域(如http://api.example.com
),这就会导致跨域问题。如果不解决跨域问题,前端的 JavaScript 代码将无法正常获取后端的数据,会在浏览器控制台中出现跨域错误提示,如 “No 'Access-Control-Allow-Origin' header is present on the requested resource
” 等。这会阻碍 Web 应用的正常开发和运行,因为很多现代 Web 应用都依赖于前端与后端之间的数据交互。所以,在进行前后端分离开发或涉及多个不同源的资源交互时,需要采取相应的措施来解决跨域问题,以确保应用的正常功能
解决跨域
下面将介绍三种解决跨域问题的方法(以前端vue,后端Springboot为例):
在前后端分离的项目中,Vue和SpringBoot解决跨域问题主要有以下几种方法:
1. Vue前端配置代理
在Vue项目的vue.config.js
文件中配置代理,将前端请求转发到后端。这样可以避免浏览器的同源策略限制。配置如下:
// 配置开发服务器相关选项
server: {
// 自动打开浏览器
open: true,
// 指定服务器运行的端口号为1010
port: 1010,
// 启用热模块替换(Hot Module Replacement,HMR)
// 在开发过程中,修改代码时,浏览器可以实时更新而无需完全刷新页面
hmr: true,
proxy: {
"/api": {
// 目标服务器地址,这里是本地的另一个服务,运行在端口1011上
target: "http://localhost:1011",
// 是否改变请求的源(Origin),设置为true时,会将请求的源修改为目标服务器的源
changeOrigin: true,
// 路径重写规则,将以/api开头的路径替换为空字符串
// 例如,请求/api/users会被转发到目标服务器的/users路径
rewrite: (path) => path.replace(/^\/api/, ""),
// 另一种常见的路径重写方式,效果与上面的rewrite函数相同
// "^/api": "",
},
},
},
2. SpringBoot后端全局CORS配置
在SpringBoot项目中,可以通过实现WebMvcConfigurer
接口并重写addCorsMappings
方法来进行全局跨域配置。配置如下:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许跨域请求的路径
.allowedOrigins("http://localhost:5173") // 允许的域名
.allowCredentials(true) // 允许携带认证信息(前后端保持一致)
.maxAge(3600) // 预检请求缓存时间,1小时
.allowedHeaders("*") // 允许的请求头
.allowedMethods("GET", "POST", "PUT", "DELETE"); // 允许的方法
}
}
这样,SpringBoot后端会允许来自指定域名的跨域请求。
3. 使用@CrossOrigin
注解
在SpringBoot中,可以在Controller类或具体的方法上添加@CrossOrigin
注解来允许跨域请求。配置如下:
@RestController
@RequestMapping(value = "/api")
@CrossOrigin
public class MyController {
@GetMapping("/get")
public String getData() {
return "Hello, World!";
}
}
这样,对于/api
路径下的所有请求,都会允许来自http://localhost:8080
的跨域请求。
通过上述方法,可以有效解决Vue和SpringBoot前后端分离项目中的跨域问题。
SpringCloud 解决跨域问题
在 SpringCloud Gateway 中,已经提供了默认的CORS实现,我们只需要通过 application.yml 做简单配置即可。
spring:
cloud:
gateway:
# 全局的跨域处理
globalcors:
# 是否将当前cors配置加入到SimpleUrlHandlerMapping中,解决options请求被拦截问题
add-to-simple-url-handler-mapping: true
# cors配置
cors-configurations:
# 拦截所有
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求(尽量使用域名)
- "http://www.taobao.com"
- "http://www.baidu.com"
allowedMethods: # 允许的的请求方式(*表示全部)
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息(*表示全部)
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 跨域检测的有效期