所谓跨域:
在前后端分离的项目中,前台一个服务,后台一个服务。
前台的一个Axios请求打进来,要访问后台Tomcat服务器Restful接口
浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略
在默认的情况下跨域是被禁止。
IP不同或者端口号不同就是跨域
HTML5带来了CORS协议解决跨域的问题
CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing),允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制,如果浏览器支持CORS、并且判断Origin通过的话,就会允许XMLHttpRequest发起跨域请求。
Access-Control-Allow-Origin:http://somehost.com 表示允许http://somehost.com发起跨域请求。
Access-Control-Max-Age:86400 表示在86400秒内不需要再发送预校验请求。
Access-Control-Allow-Methods: GET,POST,PUT,DELETE 表示允许跨域请求的方法。
Access-Control-Allow-Headers: content-type 表示允许跨域请求包含content-type
第一步:建一个前台工程放在端口号为8084上(模仿独立的前台)
Page Index
COR测试
第二步:另建一个Restful接口放在端口号为8089上(模仿独立的后台)
@RestController
@RequestMapping("/ad")
public class TestController {
@RequestMapping("/ap")
public void run(HttpServletResponse response) {
System.out.println("CRO SUCCESSFULLY");
}
}
在不做任何的处理的情况下,前台的ajax调用后台8089的/ad/ap接口会发现如下情况
F12打开后会发现控制台已经报错
其中报错信息里的这一句,正好对应了上文中的'它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制'
No 'Access-Control-Allow-Origin' header is present on the requested resource.
也就是说跨域的本质是靠Http的Header头中的Access-Control-Allow-Origin来实现跨域的。
那么也就是说如果像解决跨域问题,就必定要解决Http的Header头中的Access-Control-Allow-Origin
以下的解决方案也是我抄别人的,我这里只做研究和测试。
解决方案1:response.addHeader
在response.addHeader这个方法中加入请求发送的ip+端口号
@RestController
@RequestMapping("/ad")
public class TestController {
@RequestMapping("/ap")
public void run(HttpServletResponse response) {
response.addHeader("Access-Control-Allow-Origin", "http://localhost:8084");
System.out.println("CO SUCCESSFULLY");
}
}
此时可以成功跨域,在打开F12此时可以发现ResponseHeaders里面Access-Control-Allow-Origin已经生效了
解决方案2:Spring框架的原生注解@CrossOrigin
@RestController
@CrossOrigin("http://localhost:8084")
@RequestMapping("/ad")
public class TestController {
@RequestMapping("/ap")
public void run(HttpServletResponse response) {
// response.addHeader("Access-Control-Allow-Origin", "http://localhost:8084");
System.out.println("CO SUCCESSFULLY");
}
}
这种方式也同样成功
解决方案3: @Configration+@Bean实现自动配置重写WebMvcConfigurer
跨域的信息都封装成WebMvcConfigurer这个对象利用Spring的自动装配原理加载进去
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
//重写父类提供的跨域请求处理的接口
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
//放行哪些原始域
.allowedOrigins("*")
//是否发送Cookie信息
.allowCredentials(true)
//放行哪些原始域(请求方式)
.allowedMethods("GET","POST", "PUT", "DELETE")
//放行哪些原始域(头部信息)
.allowedHeaders("*")
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
.exposedHeaders("Header1", "Header2");
}
};
}
}
这种方式同样可以实现跨域
解决方案4:放回新的CorsFilter
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//是否发送Cookie信息
config.setAllowCredentials(true);
//放行哪些原始域(请求方式)
config.addAllowedMethod("*");
//放行哪些原始域(头部信息)
config.addAllowedHeader("*");
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
config.addExposedHeader("head1");
//2.添加映射路径
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}
这种方式同样可以实现跨域
解决方案 1 2是可以针对单个接口进行设置
解决方案 3 4是可以全局接口进行设置
-------------------------------------------------------------------------------------------------------------------------------
到这里还没有完.......其实我之前都是做Restful接口的,直到有人问我跨域的问题,我就像从来没关注过跨域问题一样,因为我在做Restful接口时以上四种的解决方案我从来没做过,但我的项目还是前后端分离,最后还上线了。
我也自己检讨了一下自己,问了自己两个问题
1为什么自己从来没关注过跨域问题。
2为什么我SpringBoot后端明明什么也没设置,一样实现了跨域。
结合百度和之前的代码
我总结了一下原因:不是没做跨域处理,而是没在后台做跨域处理,在VUE做的跨域处理
于是我用VUE-Cli脚手架生成了一个VUE的项目
模仿之前的工程写了一个demo.vue
Submit
在Config的包下index.js下,原来是用一个代理方式来实现
查了一下代理方式的原理:将域名发送给本地的服务器(启动vue项目的服务,localhost:8080),再由本地的服务器去请求真正的服务器
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target:"http://localhost:8089/",
chunkOrigins: true,// 允许跨域
pathRewrite:{
'^/api': '' // 路径重写,使用"/api"代替target.
}
}
}
}
}
测试一下,同样可以跨域成功
在F12的时候可以看到进来的请求是
但实际请求地址为:http://localhost:8084/ad/ap,因为在vue中重写了api实际为http://localhost:8084
这也是我为什么做的RustfulAPI时候什么也没设置,但依然实现了跨域。
当然这,这并不能成为自己认识不足的借口,学无止境,每一次的问题,就应该有一个解决办法。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)