跨域通信

浏览器安全限制

限制原因


网页能访问的资源必须是同源的

  • 协议相同
  • 域名相同
  • 端口号相同

主要是基于安全考虑,如果没有限制,则可以造出假网站扩展真网站的功能,cookie也变成共享
限制手段可能是浏览器阻止发出请求,或者发出请求后浏览器拦截了返回结果
不管采用什么手段跨域,都需要服务器端配合才行,跨域访问一个陌生网站基本做不到
限制的主体是浏览器,如果直接写后端代码脱离浏览器环境则无限制

利用资源加载


script标签和img标签可以加载跨域资源,把加载资源的src地址换成服务请求地址,可以实现跨域发送

局限

  • 只能发get
  • 不能接收到返回内容,发完就结束,适合访问计数场景

JSONP


JSONP(JSON with Padding),顾名思义是给JSON加上一段东西
script标签src支持跨域加载,但是直接访问json数据并不能解析
解决方法

  • 客户端请求时附带callback参数,表示处理json的函数名
  • 服务器不返回纯json,而是用客户端传来的函数名,把json作为函数的参数,即变成了js函数调用,可以被script标签解析

局限

  • 需要服务端支持
  • JSONP本质是利用script加载外部脚本的机制,只支持get请求

Iframe


iframe可以访问任何地址,但是父窗口并不能拿到跨域的iframe窗口和window.open打开的窗口的DOM

局限

  • 网页可以设置X-Frame-Options,拒绝放入iframe
  • 需要双方js配合

设置document.domain


aa.example.combb.example.com的document.domain都可以设置为.example.com
这样就实际上变成了同源访问

局限

  • 基础域名必须相同

利用window.name

同窗口下,前一个页面写入winow.name的值可以同被后一个页面访问
父窗口打开子窗口->子窗口写入window.name->子窗口跳转父窗口同源地址->父窗口访问子窗口内容

利用片段标识符

改变url后面的#不会导致页面刷新,通过这个可以传递信息
这种改变会被onhashchange监听,父窗口和子窗口都可以改变对方
父窗口打开子窗口->子窗口改变父窗口地址#->父窗口监听改变

跨文档通信

HTML5特性XDM(Cross-Document Messaging), 发送方通过window.postMessage发消息,接收方可以监听message事件

WebSocket


原生支持跨域

CORS


CORS(Cross-Origin Resource Sharing),允许发送跨域的XMLHttpRequest请求
浏览器和服务端配合完成,对用户透明,浏览器发现跨域请求,在头部增加Origin字段,服务端判定是否同意这个来源的请求
如果服务器同意来源的请求响应的头字段会包含

  • Access-Control-Allow-Origin(必须): 要么和Origin字段一样,要么是*表示接受任意来源
  • Access-Control-Allow-Credentials(可选): 服务器是否允许发cookie
  • Access-Control-Expose-Headers(可选): 服务端返回的额外非基本字段

CORS为未来的标准方法,实际上就是通过请求头和响应头,为浏览器和后端服务器提供是否允许跨域的判断依据

  • 浏览器附加请求头Origin手动预先设置无效,服务器判断是否允许附加响应头
  • 浏览器检查响应头Access-Control-Allow-Origin,判断是否允许