跨域

如何实现跨域?

javascript中实现跨域的方式总结

  • 第一种方式:jsonp请求;jsonp的原理是利用script标签的跨域特性,可以不受限制地从其他域中加载资源,类似的标签还有img.
  • 第二种方式:document.domain;这种方式用在主域名相同子域名不同的跨域访问中
  • 第三种方式:window.name;window的name属性有个特征:在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
  • 第四种方式:window.postMessage;window.postMessages是html5中实现跨域访问的一种新方式,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源。
  • 第五种方式:CORS;CORS背后的基本思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是应该失败。
  • 第六种方式:Web Sockets;web sockets原理:在JS创建了web socket之后,会有一个HTTP请求发送到浏览器以发起连接。取得服务器响应后,建立的连接会使用HTTP升级从HTTP协议交换为web sockt协议。

跨域通信的方式

  • JSONP
  • CORS
  • Hash
  • postMessage
  • WebSoket

同源策略

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

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据

同源策略限制范围

  • Cookie、LocalStorage 和 IndexDB 无法读取
  • DOM 无法获得
  • AJAX 请求不能发送

CROS跨域资源请求

CORS(Cross-origin resource sharing)跨域资源请求 浏览器在请求一个跨域资源的时候,如果是跨域的Ajax请求,他会在请求头中加一个origin字段,但他是不知道这个资源服务端是否允许跨域请求的。浏览器会发送到服务端,如果服务器返回的头中没有'Access-Control-Allow-Origin': '对应网址或 * ' 的话,那么浏览器就会把请求内容给忽略掉,并且在控制台报错 CORS限制 允许的请求方法

  • GET
  • POST
  • HEAD 允许的Content-Type
  • text/plain
  • multipart/form-data
  • application/x-www-form-ulencoded 其他类型的请求方法和Content-Type需要通过预请求验证后然后才能发送

CORS预请求

跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求。 服务器在HTTP header中加入允许请求的方法和Content-Type后,其他指定的方法和Content-Type就可以成功请求了 'Access-Control-Allow-Headers': '允许Content-Type' 'Access-Control-Allow-Methods': '允许的请求方法' 'Access-Control-Max-Age': '预请求允许其他方法和类型传输的时间'

JSONP跨域

浏览器上虽然有同源限制,但是像 srcipt标签、link标签、img标签、iframe标签,这种在标签上通过src地址来加载一些内容的时候浏览器是允许进行跨域请求的。 所以JSONP的原理就是:

创建一个script标签,这个script标签的src就是请求的地址这个script标签插入到DOM中,浏览器就根据src地址访问服务器资源 返回的资源是一个文本,但是因为是在script标签中,浏览器会执行它 而这个文本恰好是函数调用的形式,即函数名(数据),浏览器会把它当作JS代码来执行即调用这个函数 只要提前约定好这个函数名,并且这个函数存在于window对象中,就可以把数据传递给处理函数。

Hash值跨域通信

背景:在页面A下提供iframe或frame嵌入了跨域的页面B 容器页面 -> 嵌入页通信: 在A页面中改变B的url中的hash值,B不会刷新,但是B可以用过window.onhashchange事件监听到hash变化

postMessage通信

// 窗口A中
window.postMessage('data', 'http://A.com');
// 窗口B中
window.addEventListener('message', function(event) {
  console.log(event.origin);    // http://A.com
  console.log(event.source);    // A 对象window引用
  console.log(event.data);      // 数据
})

WebSoket 跨域通信

var ws = new WebSocket('wss://echo.websoket.org') //这个是后端端口

ws.onopen = function(evt) {
  ws.send('some message')
}

ws.onmessage = function (evt) {
  console.log(evt.data);
}

ws.onclose = function(evt){
  console.log('连接关闭');
}

跨域后台CORS 怎么设置

  • nodejs
  • http-proxy
  • proxy.web

(1)porxy代理

定义和用法:proxy代理用于将请求发送给后台服务器,通过服务器来发送请求,然后将请求的结果传递给前端。

实现方法:通过nginx代理;

注意点:1、如果你代理的是https协议的请求,那么你的proxy首先需要信任该证书(尤其是自定义证书)或者忽略证书检查,否则你的请求无法成功。

(2)CORS 【Cross-Origin Resource Sharing】

定义和用法:是现代浏览器支持跨域资源请求的一种最常用的方式。

使用方法:一般需要后端人员在处理请求数据的时候,添加允许跨域的相关操作。如下:

res.writeHead(200, {
    "Content-Type": "text/html; charset=UTF-8",
    "Access-Control-Allow-Origin":'http://localhost',
    'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
    'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type'
});

(3)jsonp

定义和用法:通过动态插入一个script标签。浏览器对script的资源引用没有同源限制,同时资源加载到页面后会立即执行(没有阻塞的情况下)