问题解决: 跨域问题
本文主要介绍的解决方式:
- Vue 项目中配置代理
- 后端注解 @CrossOrigin
- 继承 WebMvcConfigurer 的全局配置类
跨域其实并不是一种问题,而是浏览器的安全机制。在 Web 开发中,由于浏览器的同源策略限制,导致不同源(域、协议、端口)之间的网页访问受到限制或出现安全问题。
协议://域名:端口(如 http://localhost:8080): 同源策略表示协议、域名和端口必须一致。比如在前后端分离项目中,后端项目运行在本机的 8080 端口,前端运行在 80 端口,这样前端访问后端就会因为不同源(端口不同)导致跨域限制。
解决跨域问题可以通过下面几种方式:
- 跨域资源共享 ( CORS ):服务端设置响应头,允许特定源访问资源;
- JSONP ( JSON with Padding ):利用 Script 标签可以跨域的特性,在前端页面通过动态创建 Script 标签来获取跨域数据;
- 代理:后端通过代理将请求转发,避免前端直接跨域请求;
- 服务器设置跨域规则:配置服务器,使其允许跨域请求访问资源。
方式一:前端配置
-
Vue 项目,在 vite.config.js 文件中可添加如下代理配置,在该文件最后另起一行进行添加即可。
module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8989', changeOrigin: true, pathRewrite: { '^/api': '' } } } } }
以上配置是将带有
/api
前缀的请求进行代理,将其代理到 ‘http://localhost:8989’,并将/api
去掉 -
如果项目中的 Axios 配置文件 (我的项目中该配置的文件名是 axios.js)有配置 baseURL 完整路径的,则需要将
协议://域名:端口
部分去掉,只保留一个/api/
。这样做的目的是:所有的 Ajax 请求都会加一个/api/
前缀,然后所有带有/api
前缀的又将被代理到http://localhost:8989
,从而避免浏览器的跨域限制。
import axios from 'axios';
// 创建一个 Axios 实例,可以给所有的请求都加上一个 /api 前缀
const http = axios.create({
baseURL: '/api/'
});
export default http;
方式二:后端注解 @CrossOrigin
前面介绍的是前端配置咯,其实在后端也可以解决跨域问题。
- 在控制类上加注解 @CrossOrigin,然后通过 origins 参数指定允许跨域访问的源。
@RestController
@RequestMapping("/api/test")
//@CrossOrigin
@CrossOrigin(origins = {"http://localhost:5173", "https://xxxx.com"})
public class TestController {
// @CrossOrigin(origins = "http://xxx.icu")
@GetMapping()
public String test() {
return "test success!!!";
}
}
origins: 允许可访问的域列表;
maxAge: 准备响应前的缓存持续的最大时间(单位秒);
@CrossOrigin 后面不加任何参数,表示允许所有源访问。其后可以通过 origins 参数指定一个或多个域,表示允许这些指定的域进行访问。该注解也可以加在方法上,含义一样,表示允许跨域访问该方法。
方式三:配置全局跨域支持
创建一个继承自 WebMvcConfigurer 的配置类,重写其中的 addCorsMappings 方法来配置允许跨域的规则。(注意类上要加 @Configuration 注解表面这是一个配置类,并将其交由 Spring 容器管理)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowCredentials(true)
.allowedHeaders("token")
.maxAge(3600);
}
}
addMapping(“/**”): 指定允许跨域访问的路径,通常是所有路径;
allowedOriginPatterns(“*"): 表示允许所有的来源;
allowedOrigins(“http://xxx.com”): 表示允许指定的来源,区别在于 allowedOriginPatterns() 可以进行模式匹配,而这个需要指定明确地地址;
allowedMethods(“*”): 表示允许所有的 HTTP 方法进行跨域请求;
allowedCredentials(true): 允许跨域请求携带身份凭证 (如 cookies、HTTP 认证信息等);
allowedHeaders(“token”): 指定了允许跨域请求携带的请求头信息,这里表示只允许携带名为 “token” 的请求头;
maxAge(3600): 指定预检请求有效期,即在多久内不需要再发送预检请求,这里是 3600 秒(1 小时)。