资讯专栏INFORMATION COLUMN

跨域理解

zhongmeizhi / 1339人阅读

摘要:什么是跨域个人一句话解释如果与不同源,那么页面不能获取页面的资源。所以用同源策略来限制跨域是必须的。它是标准,是跨源请求的根本解决方法。

本文整理了一些有关跨域的基础知识和细节问题。

什么是跨域

个人一句话解释:如果 url Aurl B 不同源,那么页面A不能获取页面B的资源。这里有两个关键词:url同源,浏览器的同源策略就是针对两个url,它们满足以下三个条件,才是同源:

协议相同

域名相同

端口相同

https://www.baidu.com/

这里面有两个细节需要提及,域名是包括///的所有部分www.baidu.com;没有指定端口号默认是:80端口。

如果一个页面中的JS可以任意发起http跨域获取其他页面上的资源,这是一件很可怕的事,举个例子:

张三访问了某银行网站 abank.com,服务器端验证后会在响应头中加入Set-Cookie字段,然后下次张三再发起请求,浏览器会自动将cookie附加在HTTP请求的首部字段Cookie中,服务器端就知道张三已经登录过了。

张三接着访问了危险页面 danger.com,这个页面中写了一些Ajax,它发起请求访问abank.com,这一行为用户不能察觉,如果可以跨域发起请求,那么浏览器同样会自动将cookie附加在HTTP请求的首部字段Cookie中,这样这个危险危险网站就登陆了张三的银行账户。

所以用同源策略来限制跨域是必须的。

这里我思考了一个问题,在浏览器地址栏里输入url为什么没有出现跨域问题?
要明确,同源策略是浏览器的行为,在地址栏中输入url是用户主观行为,所以浏览器是不判为跨域的。那么同源限制的对象其实是页面中发起http请求的js。那同源限制的行为有哪些呢?有以下三种:

Cookie、LocalStorage 和 IndexDB 无法读取。

DOM 无法获得。

AJAX 请求不能发送。

接下来说说规避跨域限制的集中方式

针对AJAX的跨域 JSONP

JSONP利用的的是:

上面的script标签向服务器example.com发出请求,该请求有一个查询字符串callback参数,用来指定回调函数的名字;服务器发现请求中有callback参数,就会将JSON作为指定回调函数的参数,回调函数作为脚本返回;脚本返回后,会直接作为代码运行,这时,只要浏览器定义了foo函数,该函数就会立即调用。

JSONP的缺点在于只能发GET请求。

CORS

CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

阮一峰老师关于CORS的文章非常细致,跨域资源共享 CORS 详解,这里仅仅梳理下提纲备查。

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。

请求方法是以下三种方法之一:

HEAD

GET

POST

HTTP的头信息不超出以下几种字段:

Accept

Accept-Language

Content-Language

Last-Event-ID

Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是不同时满足上面两个条件,就属于非简单请求。

简单请求

简单请求的CORS分为以下几步:

浏览器发现AJAX请求跨源,在请求头中添加Origin字段,它的值是http请求的源url;

服务器根据Origin的值决定是否同意这次请求;

如果Origin指定的域名在服务器许可范围内,则会在报头中添加以下三个字段:

Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求.

Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器,另一方面,开发者必须在AJAX请求中打开withCredentials属性。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

Access-Control-Expose-Headers
该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段。

如果如果Origin指定的域名不在服务器许可范围内,响应头中没有Access-Control-Allow-Origin,浏览器就会抛出错误,中断这个http请求。

非简单请求

简单请求的CORS分为以下几步:

浏览器在正式请求之前,先发送一个预检请求,预检请求的请求方法是OPTIONS,请求头中带以下三个字段:

Access-Control-Request-Method
该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法

Access-Control-Request-Headers
可选,该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段

如果服务器端预检不通过,浏览器报错;如果通过,返回的响应头中包含以下几个字段:

Access-Control-Allow-Origin
一定包含

Access-Control-Allow-Methods
一定包含,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。

Access-Control-Allow-Credentials
可选

Access-Control-Max-Age
可选,用来指定本次预检请求的有效期,单位为秒,未过期的话不用再发送预检请求。

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

WebSocket

WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

针对Cookie

Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享 Cookie。

举例来说,A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那么只要在两个网页的脚本中设置的document.domain="example.com",两个网页就可以共享Cookie。

针对iframe

如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。对于完全不同源的网站,目前有三种方法,可以解决跨域窗口的通信问题:

片段识别符(fragment identifier)

window.name

跨文档通信API(Cross-document messaging),HTML5中的window.postMessage

参考文章:
浏览器同源政策及其规避方法
跨域资源共享 CORS 详解

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96483.html

相关文章

  • 用本地运行的demo快速入门跨域

    摘要:学习建议在学习其中一种跨域方法的时候,建议边运行项目里的,边在网上搜索博客文章学习这种跨域方法,这样有助于快速并且深入理解跨域。鉴于网上有很多文章详细讲述跨域知识,只是少了可以本地运行的,所以这里就不再赘述跨域知识。 前言 因为学习跨域需要配置本地服务器,可能会比较麻烦,所以自己根据网上的博客写了大多数跨域的简单demo,可以自己在本地运行,而且不用配置服务器。自己对于跨域的理解刚开始...

    yy736044583 评论0 收藏0
  • 用本地运行的demo快速入门跨域

    摘要:学习建议在学习其中一种跨域方法的时候,建议边运行项目里的,边在网上搜索博客文章学习这种跨域方法,这样有助于快速并且深入理解跨域。鉴于网上有很多文章详细讲述跨域知识,只是少了可以本地运行的,所以这里就不再赘述跨域知识。 前言 因为学习跨域需要配置本地服务器,可能会比较麻烦,所以自己根据网上的博客写了大多数跨域的简单demo,可以自己在本地运行,而且不用配置服务器。自己对于跨域的理解刚开始...

    GraphQuery 评论0 收藏0
  • 用本地运行的demo快速入门跨域

    摘要:学习建议在学习其中一种跨域方法的时候,建议边运行项目里的,边在网上搜索博客文章学习这种跨域方法,这样有助于快速并且深入理解跨域。鉴于网上有很多文章详细讲述跨域知识,只是少了可以本地运行的,所以这里就不再赘述跨域知识。 前言 因为学习跨域需要配置本地服务器,可能会比较麻烦,所以自己根据网上的博客写了大多数跨域的简单demo,可以自己在本地运行,而且不用配置服务器。自己对于跨域的理解刚开始...

    Integ 评论0 收藏0
  • JSONP跨域访问API接口深入理解

    摘要:说明关于跨域问题的解决方案多达七八种,你不要说哪有这么多,我不跟你较真哈,你也别跟我较真哈自行百度或这里不会跟你说那么多种只说使用最多的一种你要非说用的不是最多的我不信哦你信好了哈哈你开心就好关于跨域浏览器的同源策略要了解什么是跨域你需要了 说明 关于跨域问题的解决方案多达七、八种,你不要说哪有这么多,我不跟你较真哈,你也别跟我较真哈, ?!自行 百度 或 Google, 这里不会跟你...

    tunny 评论0 收藏0
  • web跨域之jsonp, cors, proxy理解

    摘要:跨域跨域产生原因协议名不一样主机不一样端口不一样跨域有无问题请求会产生问题这是浏览器处理的结果通过统一资源定位获取的图片资源也是一种跨域但是不会产生问题处理跨域的方法只支持返回响应头允许跨域开发中使用服务器代理例如一服务器端设置响 web跨域 跨域产生原因: a. 协议名不一样 b. 主机不一样 c. 端口不一样 跨域有无问题: a. ajax请求会产生问题, 这...

    wind5o 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<