知识点:
- 同源:协议,域名,端口,三者必须相等。
- 同源策略:浏览器有同源策略,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击
- 跨域条件:协议,域名,端口,有一个不同就算跨域。
应用场景:
简单的跨域请求jsonp即可,复杂的cors,窗口之间JS跨域postMessage,开发环境下接口跨域用nginx反向代理或node中间件比较方便
跨域解决方案:
- 通过jsonp跨域
- document.domain + iframe跨域
- location.hash + iframe
- window.name + iframe跨域
- postMessage跨域
- 跨域资源共享(CORS)
- WebSocket协议跨域
可以跨域的三个标签:
<img src=’***’>-----------------加载图片
<link href=’***’>-----------------加载css
<script src=’***’>-----------------加载js
JS跨域请求之JSONP(协议)
Jsonp实现原理:
script标签src属性中的链接可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。
过程:
(1)你在a页面去访问一个b页面数据时,需要传递一个callback参数给服务端,如callback=flightHandler
(2)服务端接收callback参数,用这个参数值包裹住要返回的JSON数据,
如:flightHandler({‘name’:’lichuyan’,’age’:16})(3)当远程数据一返回的时候,随着动态脚本的执行,这个flightHandler函数就会被执行。
实现:
原生JS实现
jQuery实现:
<script type="text/javascript"> function doTest(){ $.ajax({ type:"get", url :"test1.php?user=admin&password=123", dataType:"jsonp", jsonp:"callback",//传递给请求服务器处理程序或页面的,用以获得JSONP回调函数名 jsonpCallback:"jsonCallBackTest",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,此属性可不配置 success:function(data){ alert(data.user+" "+data.password); }, error:function(){ alert("error"); } }); } function jsonCallBackTest(data){ alert("jsoncallback"+data.user+" "+data.password); } </script>
缺点:
- 首先,它没有关于JSONP调用的错误处理,一旦回调函数调用失败,浏览器会以静默失败的方式处理。
- 其次,它只支持GET请求,这是由于该技术本身的特性所决定的。因此,对于一些需要对安全性有要求的跨域请求,JSONP的使用需要谨慎一点了。
html5--postMessage()
定义:
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
a.) 页面和其打开的新窗口的数据传递
b.) 多窗口之间消息传递
c.) 页面与嵌套的iframe消息传递
d.) 上面三个场景的跨域数据传递
用法:
postMessage(data,origin)方法接受两个参数
data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
应用背景:
窗口A(http://A.com)向跨域的窗口B(http://B.com)发送消息;
location.hash+iframe跨域
原理
a域与b跨域相互通信,通过中间页c来实现。三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
在url: http://a.com#helloword中的‘#helloworld’就是location.hash,改变hash并不会导致页面刷新,所以可以利用hash值来进行数据传递
具体实现
A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。
WebSocket协议跨域
定义:
WebSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。
HTML5推出了WebSocket标准,让浏览器和服务器之间可以建立无限制的全双工通信,任何一方都可以主动发消息给对方。
使用:
<script type="text/javascript">function WebSocketTest(){
if ("WebSocket" in window){
alert("您的浏览器支持 WebSocket!");// 打开一个 web socketvar ws = new WebSocket("ws://localhost:9998/echo");ws.onopen = function(){
// Web Socket 已连接上,使用 send() 方法发送数据ws.send("发送数据");alert("数据发送中...");};
ws.onmessage = function (evt){
var received_msg = evt.data;alert("数据已接收...");};
ws.onclose = function(){
// 关闭 websocketalert("连接已关闭...");};
}
else
{
// 浏览器不支持 WebSocketalert("您的浏览器不支持 WebSocket!");}
优点:HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
=================================服务器跨域============================================
在实践过程中,一般我们喜欢让服务器来多做一些处理,从而尽可能让前端简化。
CORS跨资源共享
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。
需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。
目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案
1:前端设置:
2、服务端设置 如java
若后端设置成功,前端浏览器控制台则不会出现跨域报错信息,反之,说明没设成功。
nginx反向代理
原理:
所谓反向代理服务器,它是代理服务器中的一种。客户端直接发送请求给代理服务器,然后代理服务器会根据客户端的请求,从真实的资源服务器中获取资源返回给客户端。所以反向代理就隐藏了真实的服务器。利用这种特性,我们可以通过将其他域名的资源映射成自己的域名来规避开跨域问题。
使用:
用nginx服务器时,就有这个配置文件
注意:可以配置多个