什么是跨域
- 只要协议、域名、端口有任何一个不同,都被当作是不同的域
No ‘Access-Control-Allow-Origin’ header is present on - CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
模拟情景
新建一个html页面放到桌面,单纯的一个按钮ajax访问
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>测试CORS</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(function(){
$("#cors").click(function(){
$.ajax({
url:"http://127.0.0.1:8080/index",
success:function(data){
alert(data);
}
})
});
});
</script>
</head>
<body>
<input type="button" id="cors" value="CORS跨域测试" />
</body>
</html>
快速构建一个springboot web工程,新加index controller
@Controller
public class IndexController {
@RequestMapping("/index")
@ResponseBody
public String index() {
System.out.println("我的sessionId为" + session.getId());
return "凉凉";
}
}
上面的页面访问这个控制器。访问桌面页面,提示跨域,因为相当是两个系统互相访问了。
Failed to load http://127.0.0.1:8080/index: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘null’ is therefore not allowed access.
springboot解决方案:
增加cors配置:
新建类CORSConfiguration
@Configuration
public class CORSConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**") //匹配访问的路径
.allowedMethods("*") //匹配访问的方法
.allowedOrigins("*") //匹配允许跨域访问的源 "http://localhost:8081", "http://localhost:8082"
.allowedHeaders("*"); //匹配允许头部访问
}
}
主方法同样开启自定义配置注解:@EnableAutoConfiguration
发现可以正常访问了。但是发现后台打印的sessionid每次都变。
我的sessionId为AB1CBA17EABC80F11268082A77BA8B42
我的sessionId为EE66C4D0A525B5DE1CCCC7DA08E39539
我的sessionId为45CB7EC7DCEA715D27801B31A64FEF7A
因为跨域,默认是不支持cookie,所以导致sessionid不能传给服务器。所以每次请求都是新的session。
解决方案:
ajax添加:使用cookies
xhrFields: {
withCredentials: true
}
同时全局配置设置
@Configuration
public class CORSConfiguration implements WebMvcConfigurer {
@Override
//全局配置
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**") //匹配访问的路径
.allowedMethods("PUT", "GET" , "POST") //匹配访问的方法
.allowedOrigins("*") //匹配允许跨域访问的源 "http://localhost:8081", "http://localhost:8082"
.allowedHeaders("*") //匹配允许头部访问
.allowCredentials(true);
}
}
测试访问ajax地址为:http://192.168.1.196:8080/index ,sessionid不变,其他端口不行。传统servlet的设置方式,需要指定对应的地址ip端口
response.addHeader(“Access-Control-Allow-Origin”,
“http://127.0.0.1:8020“);
response.addHeader(“Access-Control-Allow-Credentials”, “true”);
jsoup解决跨域
JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
ajax就改变个类型
$.ajax({
dataType:'jsonp',
url:"http://192.168.1.196:8080/index",
success:function(data){
alert(data);
}
})
服务端:
@Controller
@RequestMapping(value = "", method = RequestMethod.GET)
public class IndexController {
@RequestMapping(value = "/index")
public void index(HttpSession session, HttpServletResponse response, HttpServletRequest request) throws IOException {
System.out.println("我的sessionId为" + session.getId());
String callBackFuncString = request.getParameter("callback");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
//language=JSON
String json = "\"凉凉\"";
out.write(callBackFuncString + "(" + json +")");
}
}
两种方式比较
jsonp是jquery提供的跨域方式
cors是w3c提供的一个跨域标准
jsonp只支持get方式的跨域
cors支持get和post方式的跨域
jsonp支持所有的浏览器(因为所有浏览器都可以使用script标签发送请求)
cors不支持IE10以下的浏览器