跨域问题不仅影响开发效率,还可能导致项目进度延误。因此,理解和掌握跨域问题的原理及其解决方案对于前端开发者和后端开发者来说都至关重要。本文将详细介绍什么是跨域、跨域产生的原因,以及常见的后端跨域解决方案。
文章目录
一、什么是跨域
跨域
是指在浏览器的同源策略下,网页上的资源请求涉及不同的协议、域名或端口。即使两个网页属于同一网站,只要协议、域名或端口有所不同,浏览器就会认为这是跨域请求。浏览器出于安全性考虑,会阻止一些跨域请求的数据交互,导致前端无法读取跨域服务器返回的数据,通常会抛出“跨域错误”或类似的警告。
例如,前端的 Vue 应用运行在 http://localhost:8080
,而后端的 SpringBoot 服务在 http://localhost:8181
,虽然它们都在同一台机器上,但由于端口不同,浏览器会将它们视为不同的源,从而触发跨域问题。
后端可以接收到请求,也返回了响应结果。但是,浏览器拦截了响应,无法读取后端传来的数据,导致报错。
二、跨域产生的原因
跨域问题的产生主要是由于浏览器的同源策略(Same-Origin Policy)。同源策略是浏览器的一种安全机制,用于限制不同源之间的交互,以防止恶意网站通过脚本访问其他网站的敏感信息(如用户数据、Cookie等)。具体来说:
- 协议不同:例如 http://example.com 和 https://example.com。
- 域名不同:例如 http://example.com 和 http://test.example.com。
- 端口不同:例如 http://example.com:8080 和 http://example.com:8081。
只要协议、域名或端口中的任意一项不同,就会触发同源策略,导致浏览器拦截跨域请求。
示例:
Vue:http://localhost:8080
SpringBoot:http://localhost:8181/list
协议 | 域名 | 端口号 | |
---|---|---|---|
Vue | http | localhost | 8080 |
SpringBoot | http | localhost | 8181 |
是否相同 | √ | √ | × |
三、解决策略:
为了解决跨域问题,有多种方法可以通过配置来允许跨域请求。最常见的解决方案是 CORS (Cross-Origin Resource Sharing)。
1. CORS(跨域资源共享)
CORS 是一种由浏览器和服务器共同支持的机制,允许跨源请求。通过在服务器响应头中设置 CORS 相关的字段,浏览器可以允许跨域请求的读取。以下是常用的 CORS 头部字段:
Access-Control-Allow-Origin
:指定哪些源可以访问资源。值可以是 *(允许所有源)或指定的域名。Access-Control-Allow-Methods
:指定允许的 HTTP 方法,如 GET, POST, PUT, DELETE 等。Access-Control-Allow-Headers
:指定允许的请求头。Access-Control-Allow-Credentials
:是否允许携带 Cookies 或 HTTP 身份认证信息。Access-Control-Max-Age
:指定预检请求的缓存时间。
2. 在 SpringBoot 中配置 CORS
在 SpringBoot 中,你可以使用以下几种方式来配置 CORS。
2.1 在目标方法中添加@CrossOrign
注解
这种方式适用于少量的跨域请求,你可以在目标方法上直接添加 @CrossOrigin
注解来允许跨域。
@GetMapping("/list")
@crossorigin
public List<string> list(){
List<String> list = Arrays.asList("Java","c++","Go");
return list;
}
2.2 添加Cors过滤器
如果有很多接口需要支持跨域,使用全局配置更为方便,可以避免在每个方法上都加 @CrossOrigin 注解。
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 允许所有来源
corsConfiguration.addAllowedHeader("*"); // 允许所有请求头
corsConfiguration.addAllowedMethod("*"); // 允许所有HTTP方法
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration); // 适用于所有路径
return new CorsFilter(source);
}
}
2.3 实现 WebMvcConfigurer
接口,重写 addcorsMappings
方法
可以通过实现 WebMvcConfigurer 接口来更加灵活地配置跨域策略
@Configuration
public class CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*") // 允许所有来源
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
.allowCredentials(true) // 允许发送 cookies
.maxAge(3600) // 设置预检请求的缓存时间
.allowedHeaders("*"); // 允许所有请求头
}
}