zhuanlan.zhihu.com/p/104984869
同源策略的意义
浏览器基于用户的隐私安全目的,防止恶意网站窃取数据(只是浏览器有这个同源策略设置,但是用命令行curl请求某个跨域地址时能得到相应结果),不允许不同域名的网站之间互相调用ajax XHR对象,只是不允许XHR对象,对其他的图片、js脚本、css脚本还是可以通过标签跨域调用。所以css/js/img可以跨域请求(即引用),AJAX不能请求跨域的资源。
curl http://www.abc.com 用这个命令获得了http://www.abc.com指向的页面,同样,如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将不显示文件头部,即HTML文档的header。要全部显示,请加参数 -i,要只显示头部,用参数 -I。任何时候,可以使用 -v 命令看curl是怎样工作的,它向服务器发送的所有命令都会显示出来。为了断点续传,可以使用-r参数来指定传输范围。
同源策略会限制以下三种行为
【1】 Cookie、LocalStorage 和 IndexedDB 无法读取。Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。
【2】 DOM 无法获得。
【3】 AJAX 请求无效(可以发送,但浏览器会拒绝接受响应)。
跨域
解决跨域问题的两个前提特别注意:
第一,如果是协议和端口造成的跨域问题“前端”无法解决。
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。比如在host文件中可将两个不同域名绑定到同一个IP地址上形成跨域。
“URL的首部”可在console.log控制台中用window.location.方法名获取
解决跨域
解决跨域的方式很多,比如Node中间件代理、Nginx反向代理等等。这里介绍两种最简单的方式:JSONP和CORS。
JSONP
JSONP可以算是利用同源策略的“漏洞”而创造出来的跨域解决方案,属于奇巧淫技。
还记得上面Demo中,标签可以跨域得到图片吗?
这是我们突破跨域的第一个因素。
CORS
JSONP的缺点其实挺多的,百度一下就能了解到。最显著的缺点其实是JSONP只支持GET请求,毕竟它的灵感来自于
从这个角度说,CORS要比JSONP强大且灵活。
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
CORS需要浏览器和服务器同时支持。在JSONP中,前端带来了callback方法名,需要后端配合返回JS片段。而在CORS中,浏览器会自动带来一些请求头,后端需要针对这些请求头做一些处理。
简单地说:JSONP是前端代码层面带一些东西给后端,CORS则是浏览器层面带一些东西给后端。本质上都需要前后端协商。
不过目前所有浏览器都支持该功能(会自动带上请求头),IE浏览器不能低于IE10。所以最终来看,CORS这种方案不需要前端做任何事情(绝大部分浏览器支持),只需后端配合即可。
对于服务端而言:
CORS通信与AJAX没有任何差别,因此我们不需要改变以前的业务逻辑。只不过,浏览器会在请求中携带一些头信息,我们需要以此判断是否允许其跨域,然后在响应头中加入一些信息即可。这一般通过过滤器完成即可。
简单请求
只要同时满足以下两大条件,就属于简单请求。:
(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
当浏览器发现发起的ajax请求是简单请求时,会在请求头中携带一个字段:Origin.
刚才说过,CORS需要客户端和服务端同时支持。上面这个小操作,算是客户端的支持行为(IE10以下不行)。
浏览器认为只要后端没返回CORS头(Access-Control-Allow-Origin),就认为后端不允许跨域,返回的数据不可靠。
Origin中会指出当前请求属于哪个域(协议 + 域名 + 端口)。服务会根据这个值决定是否允许其跨域。
如果服务器允许跨域,需要在返回的响应头中携带下面信息(算是服务端的支持):
Access-Control-Allow-Origin: manage.leyou.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin:可接受的域,是一个具体域名或者 ***** (代表任意域名)
Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true
**
**
有关cookie:
要想操作cookie,需要满足3个条件:
服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。
浏览器发起ajax需要指定withCredentials 为true
响应头中的Access-Control-Allow-Origin一定不能为 ***** ,必须是指定的域名
这样一来,前后端都支持跨域了,那就跨吧。
**
**