[聚合文章] 跨域总结

JSONP 2017-02-23 11 阅读

如果两个页面的不具有相同的 ,即 协议端口子域名 有任意一个不同,如果使用 XMLHttpRequest 或者 fetch 就会产生跨域(跨域并非浏览器限制了发起跨站请求,而是跨站请求可以正常发起,但是返回结果被浏览器拦截了。最好的例子是CSRF跨站攻击原理,请求是发送到了后端服务器无论是否跨域!)

跨域的解决方法

CROS

CORS 是一个W3C标准,全称是” 跨域资源共享 “(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。

如何实现 CROS

CROS 需要 浏览器服务器 同时支持,关键是 服务器

简单请求

只要同时满足以下两大条件,就属于简单请求。

  1. 请求方法是以下三种方法之一:
  • HEAD
  • GET
  • POST
  1. HTTP的头信息不超出以下几种字段:
  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

基本原理

基本原理是浏览器发送的header信息中增加了一个 Origin 字段

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

然后服务器根据这个值,决定是否同意这次请求,若origin指定的源不在范围之内,服务器会返回一个不带有 Access-Control-Allow-Control 字段的信息,浏览器收到就会抛出一个错误。如果Origin指定的域名在许可范围内,服务器返回的信息会多出几个头信息字段。

// 正常返回
Access-Control-Allow-Origin: http://api.bob.com // * 的表示接受任意域名的请求
Access-Control-Allow-Credentials: true // 是否发送 cookie
Access-Control-Expose-Headers: FooBar // 获取其他指定 header 字段
Content-Type: text/html; charset=utf-8

非简单请求

请求方法是 PUTDELETE ,或者 Content-Type 字段的类型是 application/json

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为 "预检"请求 (preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

JSONP

Jsonp(JSON with Padding) 是 json 的一种”使用模式”,可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

例子

解释:客户端请求的 URL中会带有一个回调函数 ,服务器收到这个请求会将数据包装到回调函数中,然后返回给客户端,返回的函数就会 调用 客户端写的那个回调函数,也就实现了跨域访问

缺点: 只支持GET ,非常易用遭到跨站请求伪造(cross-site request forgery)的攻击

JSONP的原生使用需要动态创建script标签

<scripttype="text/javascript">
// 得到航班信息查询结果后的回调函数 
var flightHandler = function(data){ 
    alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。'); 
}; 
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) 
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; 
// 创建script标签,设置其属性 
var script = document.createElement('script'); 
script.setAttribute('src', url); 
// 把script标签加入head,此时调用开始 
document.getElementsByTagName('head')[0].appendChild(script);  
</script>

图像 Ping

<img>src 属性不用担心跨域,可以动态的创建图像,使用他们的 onloadonerror 事件处理程序来确定是否接收到了响应。 简单单向 的跨域,请求的数据是通过查询字符串形式发送的,而响应内容通常是像素图或 204 响应。

实例代码

var img = new Image();
img.onload = function(){
    console.log('done'); // 请求完成便会通知
}
img.src = "http://www.example.com/test?name=ruansongsong";

缺点

通常用于跟踪用户点击页面或动态广告曝光次数,只能用于 GET 请求, 无法访问服务器响应的文本

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。