一,啥是跨域
同源策略是浏览器最基本的安全功能。
通常域名是由以下几部分组成:
http:// www.baidu.com : 8080 / #abc
协议 域名 端口号 hash、查询字符串、文件名等
同源策略会限制以下的内容:
1,cookie、localstorage和indexDB无法读取
2,DOM无法获得
3,ajax发送后会被浏览器拦截
不过有些标签是可以允许跨域加载的:
1,img 标签
2,link 标签
3,script 文件
当协议、域名、端口号任意一个不相同时,都算作不同域。不同域之间请求资源,就是跨域。
如果是协议和端口号造成的跨域,前端是无法解决的。
在跨域的问题上,是通过 ‘url首部’来识别而不会根据域名对应的ip地址是否相同来判断。 url首部可以理解为‘协议、域名和端口必须匹配’。
跨域并不是http请求发送不出去,请求可以发出去,服务端也能接受并正常返回结果,只是结果被浏览器拦截了。
因为跨域本身是为了阻止用户获取不同域下的内容。所以表单提交这种方式是可以发起跨域请求的,因为表单只会提交不会获取新内容。
二, 跨域方法
1,jsonp
因为在页面上调用script标签没有跨域的限制(不仅如此,凡是拥有src属性的标签都具有跨域的能力)。
首先在本页面声明一个用来获取数据的回调函数, 创建一个script标签,将要跨域的地址加上该回调函数赋值给script的src属性(通过 ?callback= fn)
服务器接收到该请求后,会在返回的文件中 将该回调函数名和数据拼接起来,返回给客户端。客户端执行该回调函数,就可以获取到服务端传过来的数据。
jsonp的兼容性很好,但是仅仅只支持get请求。
2,cors
cors需要浏览器和后台同时支持。 ie8和ie9需要通过XDomainRequest实现
浏览器会自动进行cors通信,所以只要后台实现了cros,就实现了跨域。
服务端设置Access-Control-Allow-Origin就可以开启cors,该属性表示哪些域名可以访问资源。
在使用cors发送请求时,会出现两种情况:
简单请求:
只要同时满足以下两种条件就属于简单请求
条件1: 使用get 、head、post方法
条件2: content-type的值为 text/plain、 multipart/form-data、 application/x-www-form-urlencoded 三者之一。
复杂请求:
不符合简单请求的就属于复杂请求。 复杂请求的cors会在正式请求之前增加一次http查询请求(预检请求),该请求是option方法,通过该请求来知道服务端是否允许跨域请求。
3,postMessage
XMLHttpRequest Level 2的api,可以解决以下的问题:
页面和其打开的新窗口的数据传递
多窗口之间消息传递
页面和嵌套的iframe消息传递
以上三个场景的跨域数据传递
postMessage方法允许来自不同源的脚本采用异步方式进行有限的通信。
otherWindow.postMessage(message,targetOrigin,[transfer]);
message: 要发送的数据
targetOrigin:通过窗口的origin属性来指定哪些窗口能接收到消息,只有目标窗口的协议、域名和端口都和提供的targetOrigin匹配的时候,才会被发送。
transfer: 和message同时传递的Transferable对象,这些对象的所有权将被转移给消息的接收方,发送方不再保有所有权。
4,websocket
h5的一个持久化协议。实现了浏览器和服务器的全双工通信,同时也是跨域的一种解决方案。
websocket和http都是应用层协议,都基于TCP。但是websocket是一种双向通信协议,一旦连接建立,服务端和客户端都可以向对方发送或接收数据。
websocket建立的时候需要用到http协议,建立好连接之后就与http无关了。
5,Node js中间件代理
同源策略是浏览器需要遵循的标准,而如果服务端向服务端请求就无需遵循同源策略。
代理服务器接收浏览器的请求,处理后转发给服务器,收到服务器的响应后再转发给浏览器。
需要注意的是代理服务器和浏览器之间也遵循同源策略。
6,nginx反向代理
类似node中间件代理,需要搭建一个中转nginx服务器,用于转发请求。
最简单的跨域方式。只要修改nginx的配置即可解决跨域问题。
还有一些不常用的奇淫技巧,就不写了。 一般用的最多的就是cors和nginx反向代理。