什么是跨域
做web开发的时候,可能会遇到Origin null is not allowed by Access-Control-Allow-Origin这个错误。这就是因为你的请求跨域了,然后浏览器把服务器返回的结果拦截了。首要要明白的一点是,这是浏览器的行为,服务端已经响应请求了,而浏览器因为同源策略原因,把请求拦截了。那什么是同源策略呢?
同源策略
在javascript中,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。
那么什么叫相同域,什么叫不同的域呢?
当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如www.example.org),那么我们就可以认为它们是相同的域。例子看下面的列表
URL1 | URL2 | 说明 | 是否跨域 |
---|---|---|---|
http://www.xxx.com/a | http://www.xxx.com/b | 同一域名 | 否 |
http://www.xxx.com:8080/a | http://www.xxx.com/a | 不同端口 | 是 |
https://www.xxx.com/a | http://www.xxx.com/a | 协议不同 | 是 |
https://www.xxx.com/a | http://192.168.1.1/a | 域名和域名对应ip | 是 |
https://www.xxx.com/a | https://api.xxx.com/a | 主域相同,子域不同 | 是 |
https://www.xxx.com/a | https://xxx.com/a | 同一域名,不同二级域名(同上) | 是 |
https://www.xxx.com/a | https://yyy.com/a | 不同域名 | 是 |
CORS
上面说了有跨域的问题的存在,那现在该如何解决呢?
解决的方式有很多种,例如jsonp,CORS等等很多。这里我只说使用CORS.
CORS全名Cross-origin resource sharing(跨来源资源共享),它的原理就是服务端在响应的请求头中添加
Access-Control-Allow头,告诉浏览器这个资源什么域名,什么请求方式请求,我允许它跨域请求。有的人之前一直误解这个头是添加在请求头中,这个想法是错误的。因为如果是请求方自己告诉自己的,那还有什么意义。
在SpringMVC中,可以通过在Controller上添加@CORS注解来实现接口支持跨域。
示例
后端代码
@RestController
public class CorsTestController {
@GetMapping("/cors/test")
public String corsTest(){
return "success";
}
}
前端代码,前端就是点击按钮请求服务器,然后把结果展示出来。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script type="application/javascript">
function submit() {
$.ajax({
url:"http://127.0.0.1:8090/cors/test",
success:function(result){
alert(result)
}
});
}
</script>
</head>
<body>
<div>
<button onclick="submit()">请求</button>
</div>
</body>
</html>
结果
修改服务端代码,在接口上加上@CrossOrigin,再次请求
@CrossOrigin
@GetMapping("/cors/test")
public String corsTest(){
return "success";
}
仔细看两场请求服务器响应的结果,可以发现,第二次服务器响应头多了一些东西,主要就是红框的地方,这个地方就是服务器在响应头上加上了Access-Control-Allow-Origin: *,这句话简单翻译就是:权限-控制-允许-来源:全部
当然,如果只是加上@CrossOrigin,默认的就是所有的域,但是实际生产中,我们可以只想支持一些指定的,所有你还可以指定哪些域名可以访问。
===================更新2019-06-18==============
突然在网上找到一个写的更好的,传送门跨域资源共享 CORS 详解