在日常开发中,我们常常会遇到没有配置跨域文件,导致请求失败,这个时候就得我们前后端商讨如何解决、谁去解决问题了,为了前后端的和谐,我将分别介绍前后端处理跨域问题的解决方案
跨域是如何引起的
首先我要解决跨域就得先了解一下跨域,跨域问题(CORS,Cross-Origin Resource Sharing)通常由浏览器的同源策略(Same-Origin Policy, SOP)引起,这是一种用于保护用户安全的浏览器机制。主要原因在于,当浏览器发起请求时,如果请求的目标资源和当前页面的源(协议、域名、端口)不一致,浏览器会默认阻止这些跨域请求,造成“跨域”问题。以下是详细的原因:
1. 同源策略(Same-Origin Policy)
同源策略是一种浏览器安全机制,用于防止恶意网站通过跨站请求窃取数据。所谓“同源”指的是协议、域名、端口必须完全相同。如果三者中任何一个不同,都会被视为“跨域”。例如:
- http://example.com 与 https://example.com 是跨域的(协议不同)
- http://example.com 与 http://api.example.com 是跨域的(子域名不同)
- http://example.com:8080 与 http://example.com 是跨域的(端口不同)
2. 跨域请求场景
跨域问题主要出现在以下场景:
- Ajax 请求: 当前端发送 XMLHttpRequest 或 Fetch 请求时,请求的目标服务器与页面源不一致时,会被浏览器阻止。
- WebSocket 连接: 如果 WebSocket 连接的 URL 与页面源不一致,也会被阻止。
- 嵌套的资源请求:
<script>
、<link>
、<img>
等标签中请求的资源来源不同也会引发跨域问题。
3. 简单请求与复杂请求
- 简单请求: 请求方法是
GET
、POST
或HEAD
,并且请求头满足某些条件的请求(例如,没有自定义头)。对于简单请求,浏览器会发送请求,但如果服务器没有返回正确的 CORS 头信息(Access-Control-Allow-Origin
),浏览器将拒绝访问响应结果。 - 复杂请求: 如
PUT
、DELETE
、PATCH
请求,或使用了特殊请求头(如Content-Type: application/json
),浏览器会先发送一个OPTIONS
预检请求(Preflight Request),询问服务器是否允许该请求。如果预检请求失败,则实际请求不会发送。
前端解决跨域方案:
1. 使用代理(最常见)
在Vue CLI项目中,可以通过配置开发服务器的代理来解决跨域问题,
在项目根目录下创建或修改 vue.config.js
文件,添加以下配置:
module.exports = {
devServer: { proxy:
{ '/api':
{ // 目标服务器地址
target: 'http://example.com',
// 是否改变请求源
changeOrigin: true,
// 重写路径
pathRewrite: { '^/api': '' },
},
},
},
};
//访问 `/api` 路径时,会被代理到 `http://example.com`,可以根据需求修改目标地址。
2. ### 使用nginx反向代理
在生产环境中使用nginx,可以通过配置nginx的反向代理来解决跨域问题。
server {
listen 80;
server_name yourdomain.com;
location /api {
proxy_pass http://example.com; # 目标服务器地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
后端解决跨域方案:
后端处理跨域问题基本上都是通过使用设置CORS(跨域资源共享)来实现。
1.### 基于Spring 用于配置 CORS 配置
@Configuration //创建一个配置类
/**
* 告诉浏览器,我允许哪些服务器访问,哪些请求方式访问,是否运行携带请求头
*/
public class GlobalCorsConfig {
@Bean //把手动创建好的CorsFilter对象交给Spring管控
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//2.设置哪些域名可以访问
config.addAllowedOriginPattern("http://localhost:*");
config.addAllowedOriginPattern("http://localhost");
//3.是否允许发送Cookie信息(是否允许指定的域名携带cookie访问我当前服务)
config.setAllowCredentials(true);
//4.允许的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
//5.允许的头信息(我当前服务允许你携带所有的请求头信息)
config.addAllowedHeader("*");
//6.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new
UrlBasedCorsConfigurationSource();
// 所有的请求,都遵循以上的配置信息
configSource.registerCorsConfiguration("/**", config);
//7.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}
2.Spring Boot 中进行全局配置,适用于所有控制器。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许所有路径
.allowedOrigins("http://example.com") // 允许特定来源
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法
.allowCredentials(true);
}
}