跨域问题是怎样造成的

跨域问题的由来

相信很多人都或多或少了解过跨域问题,尤其在现如今前后端分离大行其道的时候。

你在本地开发一个前端项目,这个项目是通过 node 运行的,端口是9528,而服务端是通过 spring boot 提供的,端口号是7001。

当你调用一个服务端接口时,很可能得到类似下面这样的一个错误:

request-blocked-by-cors.jpg

然后你在发送请求的地方debug,在出现异常的地方你将得到这样的结果:

blocked-error.jpg

异常对象很诡异,返回的 response 是 undefined 的,并且 message 消息中只有一个"Network Error"。

看到这里你应该要知道,你遇到跨域问题了。

但是你需要明确的一点是,这个请求已经发出去了,服务端也接收到并处理了,但是返回的响应结果不是浏览器想要的结果,所以浏览器将这个响应的结果给拦截了,这就是为什么你看到的response是undefined。

浏览器的同源策略

那浏览器为什么会将服务端返回的结果拦截掉呢?

这就需要我们了解浏览器基于安全方面的考虑,而引入的 同源策略(same-origin policy) 了。

早在1995年,Netscape 公司就在浏览器中引入了“同源策略”。

最初的 “同源策略”,主要是限制Cookie的访问,A网页设置的 Cookie,B网页无法访问,除非B网页和A网页是“同源”的。

那么怎么确定两个网页是不是“同源”呢,所谓“同源”就是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

the-compose-of-domain.jpg

没有同源策略的保护

那么为什么要做这个同源的限制呢?因为如果没有同源策略的保护,浏览器将没有任何安全可言。

老李是一个钓鱼爱好者,经常在 我要买(51mai.com) 的网站上买各种钓鱼的工具,并且通过 银行(yinhang.com) 以账号密码的方式直接支付。

这天老李又在 51mai.com 上买了一根鱼竿,输入银行账号密码支付成功后,在支付成功页看到一个叫 钓鱼(diaoyu.com) 的网站投放的一个"免费领取鱼饵"的广告。

老李什么都没想就点击了这个广告,跳转到了钓鱼的网站,殊不知这真是一个 “钓鱼” 网站,老李银行账户里面钱全部被转走了。

no-same-origin-policy.jpg

以上就是老李的钱被盗走的过程:

1.老李购买鱼竿,并登录了银行的网站输入账号密码进行了支付,浏览器在本地缓存了银行的Cookie

2.老李点击钓鱼网站,钓鱼网站使用老李登录银行之后的Cookie,伪造成自己是老李进行了转账操作。

这个过程就是著名的CSRF(Cross Site Request Forgery),跨站请求伪造,正是由于可能存在的伪造请求,导致了浏览器的不安全。

那么如何防止CSRF攻击呢,可以参考这篇文章:如何防止CSRF攻击?

同源策略限制哪些行为

上面说了 **同源策略 **是一个安全机制,他本质是限制了从一个源加载的文档或脚本如何与来自另一个源的资源进行交互,这是一个用于隔离潜在恶意文件的重要安全机制。

随着互联网的发展,"同源策略"越来越严格,不仅限于Cookie的读取。目前,如果非同源,共有三种行为受到限制。

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) 请求的响应被拦截。

虽然这些限制是必要的,但是有时很不方便,合理的用途也会受到影响,所以为了能够获取非“同源”的资源,就有了跨域资源共享。

跨域资源共享

看到这里你应该明白,为什么文章开头的请求会被拦截了,原因就是请求的源和服务端的源不是“同源”,而服务端又没有设置允许的跨域资源共享,所以请求的响应被浏览器给拦截掉了。

CORS 是一个 W3C 标准,全称是"跨域资源共享"(Cross Origin Resource Sharing),它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了只能发送同源请求的限制。

CORS实现机制

那跨域资源共享机制是怎样实现的呢?

当一个资源(origin)通过脚本向另一个资源(host)发起请求,而被请求的资源(host)和请求源(origin)是不同的源时(协议、域名、端口不全部相同),浏览器就会发起一个 跨域 HTTP 请求 ,并且浏览器会自动将当前资源的域添加在请求头中一个叫 Origin 的 Header 中。

当然了,有三个标签本身就是允许跨域加载资源的:

你可能感兴趣的:(跨域问题是怎样造成的)