当一个请求url的 协议 、 域名、 端口 三者之间任意一个与当前页面url不同即为跨域。
例如:当前页面为http:127.0.0.1:8080
当发生如下请求时,代表发生跨域
请求地址 | 原因 |
---|---|
https://127.0.0.1:8080 | 协议不同 |
http://192.168.0.1:8080 | 域名不同 |
http://127.0.0.1:80 | 端口不同 |
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的。javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。
在前后端分离项目中,前端和后端的端口号往往会不同,导致发生跨域问题。目前我所知可以使用以下方案来进行处理。
浏览器将CORS分成两类:简单请求和非简单请求。
其中非简单请求比简单请求多了一步:
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在Header中增加一个Origin字段。如果浏览器发现跨源AJAX请求是简单请求,就自动在头信息之中,添加一个Origin字段。服务器根据Origin的值决定是否同意这次请求。如果同意,则会在响应头中加上一个属性Access-Control-Allow-Origin
下面是实现springboot中实现CORS的几种方式:
@RestController
//value属性表示接收的当前请求地址,不写表示接收所有地址
//allowCredentials=true表示接收前端传来的cookie
@CrossOrigin(value = "http://localhost:7070",allowCredentials = "true")
public class AxiosController {
}
这样做的话,每一个控制类上都要加上这个注解,比较麻烦,不推荐
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
//*表示匹配所有
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.maxAge(3600)
.allowCredentials(true);
}
}
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
//允许什么地址进行跨域请求
corsConfiguration.addAllowedOrigin("http://localhost:8888");
//允许携带cookie
corsConfiguration.setAllowCredentials(true);
//允许访问哪些方法
corsConfiguration.addAllowedMethod("*");
//允许携带哪些请求头
corsConfiguration.addAllowedHeader("*");
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
//对当前项目下的哪些请求进行cors处理
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
当我们的后端没有配置CORS时,可以在前端中使用代理服务器来解决跨域问题
由客户端请求代理服务器,再由代理服务器请求目标服务器,目标服务器将数据返回代理服务器,代理服务器再将数据返回客户端。
如果是Vue项目,可以在项目的vue.config.js添加如下配置来处理
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer:{
port:7070,
proxy: {
'/api': {
//要代理到的服务器,可以是域名也可以是ip+端口号;
target: 'http://localhost:8080',
//虚拟托管网站,如果为true,源服务器获取的req.header的信息就是他自己的header,如果为false 那么获取的header信息就是代理服务器的
changeOrigin: true,
},
},
}
})