跨域问题详解

浅谈跨域

阅读须知: 做者是一个在校大学生,还没有工做,如下内容依据我的理解与网上资料编写。如有错误,还请指出,感激涕零。网上对于跨域的解释大可能是一堆文字,对于初学者来讲每每较难理解,这篇博客我将利用NodeJs搭建一个简易的服务器用于模拟跨域,不懂NodeJs的小伙伴也不用紧张,只是借助于NodeJs来快速搭建一个http服务器。我将以最简单的代码去还原跨域问题。如有兴趣的小伙伴,可自行百度学习(菜鸟教程)。本篇博文全部代码均已跑通且会上传至我的仓库。欢迎各位指正错误。

1.跨域是什么?

跨域.PNG
这就是一个跨域引发的错误。或许许多小伙伴,一遇到错误就直接百度寻找答案,但有时候咱们不妨看看错误信息,这对咱们理解问题可能会有不错的帮助,而不是遇到问题就百度,goole。咱们来看看错误信息都告诉咱们什么?javascript

Access to XMLHttpRequest at 'http://127.0.0.1:8002/index.html' from origin 'http://127.0.0.1:8001' has been blocked by CORS policy: No'Access-Control-Allow-Origin' header is present on the requested resource.

咱们把它丢到百度翻译能够的到以下解释:html

CORS策略已阻止从“http://127.0.0.1:8002/index.html”源“http://127.0.0.1:8001”对XMLHttpRequest的访问:请求的资源上不存在“Access-Control-Allow-origin”头java

咱们把它理顺一下能够变成:node

一个网页请求另一个网页的资源被CORS策略给阻止了,缘由XMLHttpRequest的请求不存在“Access-Control-Alloworigin"头,若是你恰巧有网络协议方面的知识储备,或许你已经了解跨域是什么了,以及如何解决。web

咱们能够在简化一下这个信息:网页间的XMLHttpRequest请求被CORS策略给阻止了。好的,来到这里咱们已经知道了跨域请求失败的缘由是什么了。CORS策略阻止了它!!ajax

CORS是什么?

(推荐阅读MDN的文章:中文版:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS ,英文版:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)json

CORS:Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin. A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own.后端

由上边的介绍可知:CORS是不一样域之间资源共享的一种机制,它使用额外的Http头来告诉浏览器让运行在一个 origin (domain) 上的Web应用被准许访问来自不一样源服务器上的指定的资源。当一个资源从与该资源自己所在的服务器不一样的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。跨域

跨域的安全限制,主要是针对浏览器端来讲的,服务器端是不存在跨域安全限制的。。因此咱们能够经过代理服务器去解决跨域问题。浏览器

域:简单理解由协议+域名+端口组成

譬如文章开头图片中的两个域http://127.0.0.1:8002/index.html与http://127.0.0.1:8001是因为端口号不一样而形成了跨域。http是他们的协议,127.0.0.1是他们的Ip地址,这里是本机Ip。8001,8002是他们的端口号,简单点说ip地址是你的电脑在网络世界里的标识。(Ip不是惟一不变的,它随着你接入的网络可能会发生改变,每台电脑的网卡还有一个物理地址MAC地址。MAC地址用于在网络中惟一标示一个网卡,一台设备如有一或多个网卡,则每一个网卡都须要并会有一个惟一的MAC地址,这里不过多赘述,之后或许会更新相关内容的博文)

2.跨域的缘由是什么

虽然在上边的翻译中告诉咱们是由于CORS策略给阻止了请求,但咱们经过查阅CORS在MDN上的解释能够知道,CORS是不一样域之间共享资源的一种机制,也就是说它能够说是解决跨域的一种方案。那么引发跨域的缘由是什么?

上面说到跨域只存在于浏览器之间,这是由于浏览器存在有一个同源策略。什么是同源策略(SOP)呢?能够看一看MDN上的文章(https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy)。

同源策略是浏览器的一个安全功能,不一样源的客户端脚本在没有明确受权的状况下,不能读写对方资源。因此xyz.com下的js脚本采用ajax读取abc.com里面的文件数据是会被拒绝的。同源策略限制了从同一个源加载的文档或脚本如何与来自另外一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

阮一峰的博客中有一段跨域同源策略的描述

同源政策的目的:是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种状况:A网站是一家银行,用户登陆之后,又去浏览其余网站。若是其余网站能够读取A网站的Cookie,会发生什么?很显然,若是 Cookie 包含隐私(好比存款总额),这些信息就会泄漏。更可怕的是,Cookie 每每用来保存用户的登陆状态,若是用户没有退出登陆,其余网站就能够冒充用户,随心所欲。由于浏览器同时还规定,提交表单不受同源政策的限制。因而可知,"同源政策"是必需的,不然Cookie 能够共享,互联网就毫无安全可言了。

在这里简单介绍一下cookie,由于理解了cookie能更好的理解浏览器与服务器间的交互。咱们知道浏览器与服务器间使用过http协议来进行交互的,可是HTTP协议是无状态的,服务器是没法经过接收到的HTTP请求来区分是哪一个用户发起的请求,即服务器不知道用户上一次作了什么,这严重阻碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两饮料。最后结账时,因为HTTP的无状态性,不经过额外的手段,服务器并不知道用户到底买了什么。为了作到这点,就须要使用到Cookie了。服务器能够设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。

如何查看Cookie?

能够打开菜鸟教程里有关cookie的介绍https://www.runoob.com/js/js-cookies.html

Cookie.PNG

各位能够发现Cookies是有分组的,每一个域下边存在有不一样的cookie值,Cookie是由服务端生成的,发送给客户端(一般是浏览器)的。Cookie老是保存在浏览器中。

img

当浏览器与服务器之间通讯时,浏览器会在每一个http请求中携带当前域下的cookie。

到这里咱们已经大概了解什么是同源策略,为何要有同源策略。

同源策略限制的行为:

(1) 没法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB。

(2) 没法接触非同源网页的 DOM。

(3) 没法向非同源地址发送AJAX请求(能够发送,但浏览器会拒绝接受响应)。

不受同源策略限制的状况:

有一些状况是不受同源策略的影响,简单列举以下:

(1)页面中的超连接,点击能够访问其余不一样源的页面。

(2)表单提交,不一样源的页面能够相互提交表单数据。

(3)经过Html标签请求资源,如scrpit,img标签。

3.解决跨域

这里介绍三中种跨域的解决方案 JSONP,代理服务器和CORS

JSONP

JSONP利用的是经过HTML标签请求资源,不受同源策略影响。它的基本思想是,网页经过添加一个script元素,向服务器请求数据,这种作法不受同源策略限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。 先贴上一段网上摘抄的代码
# 预先定义好处理数据的回调
function CallbackName(data) {
  console.log('Your public IP address is: ' + data.ip);
};
# 建立scrpit元素请求资源,以备后用
function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}
# 在页面加载完成时调用函数发送指定目标请求
window.onload = function () {
  addScriptTag('http://example.com/ip?callback=CallbackName');
}

初次看这代码时不太理解,由于当时没有接触后端开发,没法理解它们的交互过程。咱们要明白一点script标签请求回来的数据浏览器是当成JS去解析的,咱们能够简单验证一下,虽然没有资料讲述这一部分的内容。

1.PNG
script1.js代码以下

<h1>11111</h1>

script2.js代码以下

alert(1);

当把这个页面打开,会发现页面弹出两次弹框,控制台提示没法解析h1标签的错误。因此能够大概理解浏览器是将请求回来的数据当成js代码执行。

这时候咱们就能够经过URL所带的queryString传递咱们的函数名,例以下边这个URL传递了CallbackName做为回调函数的名称,而原先的JS代码又预先定义了回调函数。当后代给咱们返回,Callbackname({dataObj})这样的字符串时,浏览器就会自动调用预先定义的回调函数,而须要的数据就经过{dataObj}传递过来了,因而实现了跨域请求。仍是不太理解的小伙伴能够去个人仓库里查看相关代码。

http://example.com/ip?callback=CallbackName

JSONP只能支持get请求,而且先后端须要商量好回调函数的名称。

CORS与代理服务器相关内容,我过两天整理后再更新,累了

相关文章
相关标签/搜索