跨域
跨域
同源
同源:如果两个 URL 的 protocol、port (en-US) (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。
同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。
目的:它能帮助阻隔恶意文档,减少可能被攻击的媒介。
当两个URL的协议,或端口,或主机(域名)不同时,都不构成同源,此时无法进行资源交流。
这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。(“元组” 是指一组项目构成的整体,双重/三重/四重/五重/等的通用形式)。
随着互联网的发展,”同源政策”越来越严格。目前,如果非同源,共有三种行为受到限制。
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。下面,我将详细介绍,如何规避上面三种限制。
但是注意:同源策略是针对浏览器而言的,客户端和服务器并不存在同源策略的概念。在出现非同源情况时,客户端如果向服务器发送GET请求,请求本身会成功发送,服务器得到请求也会返回响应。只是浏览器的同源策略导致客户端拿不到服务器返回的response。
跨域
目前,如果非同源,共有三种行为受到限制。
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。下面,我将详细介绍,如何规避上面三种限制。
若要实现服务器与客户端间的跨域通信,可以使用JSONP和CORS两种方法。
兼容IE:选择JSONP
JSONP基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
具体地,在某些浏览器不支持cors进行跨域时,通过请求一个js文件,在这个js文件中执行一个回调,而回调中有我们需要的跨域数据。其中,回调的名字可以使用random随机生成,这个名字以callback参数传给后台,后台将函数返回并执行。
实际中,以上方法可能存在一个缺陷:就是第三方网站可能调用 JSONP 。这可以通过使用 Header 的 Referer 字段告诉浏览器用户在访问当前资源之前的位置,进而实现用户跟踪。
浏览器的 JavaScript 引擎提供document.referrer 属性,可以查看当前页面的引荐来源。
具体地,如果 Referer 字段的网址是 JSONP 允许地网址,就放行。否则,就会屏蔽。
jsonp的优点
①兼容ie
②可以实现跨域
jsonp的缺点
①由于jsonp使用<script>标签,它无法像Ajax那样能读到精确状态码,也无法读到响应头,而只知道请求成功失败状态;
②script标签只能发送get请求,不支持post请求
CORS(Cross-origin resource sharing)
CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
简单请求
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
- HEAD
- GET
- POST
(2)HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值
application/x-www-form-urlencoded、multipart/form-data、text/plain
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。
(1)Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
(2)Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
(3)Access-Control-Expose-Headers
该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值。
非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
非简单请求具体见MDN:跨源资源共享(CORS) - HTTP | MDN (mozilla.org)
CORS与JSONP的比较
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
版权声明:本文作者为「Andy8421」.本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!