跨域问题

1.跨域问题的产生原因?

1.1 同源策略

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

例子:http://www.example.com/dir/page.html 这个网址,协议是http,域名是www.example.com,端口是80

[!NOTE] 同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。是浏览器做的努力

1.2 同源策略限制范围

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

2 跨域通信的解决方法?

2.1 CROS跨域资源请求

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

2.1.1 CORS限制

允许的请求方法

  • GET
  • POST
  • HEAD

允许的Content-Type

  • text/plain
  • multipart/form-data
  • application/x-www-form-ulencoded

其他类型的请求方法和Content-Type需要通过预请求验证后然后才能发送

2.1.2 CORS预请求

[!NOTE] 跨域资源共享标准新增了一组 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': '预请求允许其他方法和类型传输的时间'

2.2 JSONP跨域

2.2.1 基本概念

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

2.2.2 跨域原理

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

2.3 Hash值跨域通信

[!NOTE] 背景:在页面A下提供iframe或frame嵌入了跨域的页面B

容器页面 -> 嵌入页通信:

在A页面中改变B的url中的hash值,B不会刷新,但是B可以用过window.onhashchange事件监听到hash变化

2.4 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);      // 数据
})

2.5 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('连接关闭');
}

results matching ""

    No results matching ""