目录
1、同源策略
源:在任何网站的控制台输入:window.origin 或 location.origin 可以得到当前源。源 = 协议+域名+端口号。
在说跨域之前,不得不先说一下浏览器的 同源策略。同源策略是浏览器的一个安全功能,同源是指两个网址的 协议、域名、端口号 都相同,三者中只要有一个不同就是不同源。受同源策略的影响,运行在不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源,比如 abc.com 下的 JavaScript 脚本采用 Ajax 读取 xyz.com 里面的文档数据是会被拒绝的。这种浏览器的同源策略本意是防御非法攻击的,但是在前端开发中由于同源策略的存在,使得 Ajax 请求跨域数据时失败。针对这一问题衍生出了很多种解决跨域问题的方式,其中具有代表性的有 JSONP 和 CORS。
简而言之,同源策略:不同源的页面之间,不准互相访问数据。
上面的举例:abc.com 下的 JavaScript 脚本采用 Ajax 读取 xyz.com 里面的文档数据是会被拒绝的。只是为了方便描述和理解同源策略,实际上 Ajax 请求并不会被拦截。其背后 Ajax 请求跨域获取数据失败的真正原理是:浏览器禁止使用与当前网页不同来源的数据。当客户端浏览器向服务器发送跨域的 Ajax 请求时:(1)浏览器其实是发出了请求的、(2)请求也确实成功了,服务器也返回结果给客户端浏览器了、(3)但是因为响应结果中带着响应头,记录着数据来源的 IP 地址。所以,当浏览器查验服务端返回的数据时,发现响应头激活中的 IP 不是当前网页的 IP,就不会使用请求回来的数据。
问题 1:如果客户端电脑直接通过网址访问服务器,是不是就可以拿到数据了?答案是可以的,但是考虑到实际情况,一般不会出现这种情况的,因为基本上都是用户访问一个网站,在网站中做一些操作会发送一些服务器请求。
问题 2:为什么会出现跨域问题?现实情况中,为了保证项目的性能优化,和服务器的负载均衡,一般都会把服务器进行拆分几个部分:(1)web服务器:处理静态资源、(2)data服务器:做业务逻辑和数据分析、(3)图片服务器:专门为图片和视频等媒体资源设置一个服务器。如果这几个服务器的协议、域名、端口号有不同,就会导致了跨域的问题。
上一篇博客写到的 基于 JSONP 实现跨域 的方法虽然好,但是有一点缺陷就是,它只支持 GET 请求,不支持 POST 请求。如果需要支持 POST 请求怎么办,这个时候就需要用到 CORS 方式解决跨域了。
2、CORS 是啥
CORS 是一个 W3C 标准,全称是 "跨域资源共享"(Cross-origin resource sharing),它新增的一组 HTTP 首部字段,允许服务器声明哪些来源的请求有权访问当前资源,从而克服了 Ajax 只能同源使用的限制。
Ajax 请求跨域获取数据,服务器返回数据给客户端后,浏览器会用 CORS 策略查验服务器返回的数据,检查当前网页地址栏的地址是否等于返回数据的地址,如果两者不同,则浏览器就不会使用服务器响应给客户端的数据,并报错:"Access-Control-Allow-Origin" 的错误。
记住:response.setHeader('Access-Control-Allow-Origin','url') 。都得文档里,去看 MDN文档。
3、CORS 的原理
基于 Ajax 请求跨域获取数据失败的真正原理是:浏览器禁止与当前网页不同来源的数据被使用。CORS 的解决办法是,在服务端程序中,在发送消息之前手动修改响应头,将带有客户端浏览器的 IP 地址的数据包发送给客户端浏览器,然后客户端浏览器在查验服务端返回的数据时,发现响应头激活中的 IP 和当前网页的 IP 一样,那浏览器就认为这个数据包合法,可以使用该数据。代码如下:
//服务器端:服务器的地址为:127.0.0.1
const http = require("http"); //引入支持接受请求,返回响应的模块http
http.createServer((req,res) => { //创建服务端程序实例,每当有客户端发来请求时,自动调用回调函数
res.writeHead(200,{
"Access-Control-Allow-Origin":"http://客户端网页地址栏中的地址"; //可以写 *,表示允许所有的跨域请求
}), //但是,如果写 *,就不允许请求中带cookie,目的是为了保证安全性
var sentry = "这是客户端要的数据";
res.write(sentry);
res.end();
}.listen(3000); //监听3000端口
//客户端:向服务器发送Ajax请求 --实际结果客户端并请求不到数据
$.ajax({
url:'http://127.0.0.1:3000',
type:"get",
success:function(result){
alert(result);
}
})
4、CORS 的优缺点
CORS 和 JSONP 的优点与缺点大致互补,下面通过对比介绍两种跨域方式的优缺点:
(1)JSONP 只支持 GET 请求,不支持 POST 请求。但 CORS 支持 POST 在内的所有类型的 HTTP 请求。
(2)JSONP 相对于 CORS 的优势在于对浏览器的支持较好,虽然目前主流浏览器支持 CORS,但 IE10 以下不支持CORS
(3)CORS 相对于 JSONP 来说,前端需要做的事情比较少。而 JSONP 需要客户端和服务器都支持。
解释:为什么前端需要做的事情比较少,因为通过 JSONP 的方式实现跨域请求时,需要同时修改客户端和服务器的相关代码才能实现 Ajax 请求跨域获取数据的目的。而通过 CORS 的方式实现跨域请求时,只需要改写服务器配置的响应头即可。
(4)JSONP 只会发一次请求;而对于复杂请求,CORS 会发两次请求。