跨域,实质上是浏览器的一种保护处理。如果产生了跨域,服务器在返回结果时就会被浏览器拦截(注意:此时请求是可以正常发起的,只是浏览器对其进行了拦截),导致响应的内容不可用
也就是请求的URL和页面所在的URL的首部不同时就会产生跨域
实现原理:
浏览器允许一些带src属性的标签跨域,也就是在某些标签的src属性上写url地址是不会产生跨域问题
<script src="http://test/json"></script>
这样就可以获取到信息了
jsonp({
"name":"test",
"age":"123"
})
而对于JS而言,这个其实就对应一个普通的函数调用:
jsonp(...params)
所以需要定义一个jsonp函数:
var jsonp = function (data){
console.log(data)
}
可以约定一个callback参数来指定是否返回jsonp格式的数据
http://test?callback=jsonp
后台可以根据这个参数来决定返回什么格式的数据
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
浏览器在发起真正的请求之前,会发起一个OPTIONS类型的预检请求,用于请求服务器是否允许跨域,在得到许可的情况下才会发起 Real Request
常用的几种CORS请求头
Access-Control-Allow-Origin
取值表示允许的站点,使用URL首部匹配原则
Access-Control-Allow-Origin: http://test
Access-Control-Allow-Origin: * //匹配所有站点
Access-Control-Allow-Methods
仅仅在预检请求的响应中指定有效,用于表明服务器允许可跨域的方法类型,多个方法用逗号隔开
Access-Control-Allow-Headers
仅仅在预检有效,用于表明服务器允许携带的首部字段,如果请求头里面有其中没有的头类型,则不允许跨域
Access-Control-Max-Age 、
表示此次预检请求的有效期,在有效期内,预检请求不需要再次发起
浏览器将请求分为两类,一类是简单请求,一类是非简单请求,满足下列条件的就是简单请求,否则即使非简单请求:
1、请求方式:HEAD、GET、POST
2、请求头信息:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type 对应的值是以下三个中的任意一个
application/x-www-form-urlencoded
multipart/form-data
text/plain
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
简单请求和复杂请求的区别:
简单请求:一次请求
非简单请求:两次请求,在发送数据之前会先发第一次请求做预检,只有预检通过后在发一次请求作为数据传输。
关于预检请求:
请求方式:OPTIONS
“预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
如何“预检”
=> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
=> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers
首先编写一个配置源:
@Bean
public CorsConfigurationSource corsConfigurationSource(){
CorsConfigurationSource corsConfigurationSource = new CorsConfigurationSource();
// 设置Access-Control-Allow-Origin
corsConfigurationSource .setAllowedOrigins(Arrays.asList("http://www.baidu.com"));
// 设置Access-Control-Allow-Methods
corsConfigurationSource .setAllowedMethods(Arrays.asList("POST","GET"));
// 允许带凭证
corsConfigurationSource.setAllowCredentials(true);
// 对所有的url生效
UrlBasedCorsConfiguratioSource source = new UrlBasedCorsConfiguratioSource ();
source.registerCorsConfiguration("/**",corsConfigurationSource );
return source
}
开启CORS:
http....
// 开启CORS
.cors()
.and()
......