跨域HTTP请求解决方案

持续更新地址:http://jaylin.wang/2017/cross...html

跨域HTTP请求是指当前文档访问其余源提供的资源。两个页面具备相同的协议,域名和端口,则两个页面属于相同的源,不一样子域名之间也属于不一样的源。这是浏览器端的同源策略的约束,同源策略则是浏览器隔离潜在恶意文件的安全机制。git

目前经常使用的跨域解决方案有EmbedPing、JSONP、CORS。github

一些知识点

  1. 跨域限制是浏览器的一种行为ajax

    当咱们在浏览器的一个页面中尝试进行一次跨域操做,好比咱们在 localhost 的一个页面经过 ajax 访问 127.0.0.1 的一个路由,127.0.0.1已经将数据返回给浏览器,浏览器禁止了获取响应数据行为。咱们能够看一张图:json

    跨越请求现象

  2. 跨域请求的几种方式跨域

    • 跨域写
      浏览器始终支持经过跨域写操做。例如经过表单提交方式向其余源提交数据,点击连接重定向到其余源。浏览器

    • 跨域嵌入
      浏览器始终支持跨域资源的嵌入。例如经过 img、script、video 等元素的 src 属性嵌入跨域资源。缓存

    • 跨域读安全

跨域的解决方案

EmbedPing

这是我本身瞎取的一个名字,大体是利用浏览器支持标签嵌入跨域属性实现的一种方案。img、script、link[rel='stylesheet']会在页面渲染过程当中请求其src/href设置的资源地址,咱们能够在访问的路由中作处理。例如使用img的src属性:服务器

<script>
    var img = new Image()
    img.src = 'http://localhost:4000/check'
  </script>

由于没法获取到服务端返回的数据,EmbedPing是浏览器向服务器单向请求的过程。

咱们可使用 EmbedPing 作一些不严格统计。

JSONP

JSONP也利用了 script 标签的 src 属性,浏览器会执行加载成功后的js。JSONP的局限是只能发送一个GET请求。

应用示例

看一个简单示例,咱们但愿在当前域的页面上打印服务器的一个状态,咱们使用JSONP能够这样实现,前能够看一段简单代码(服务端使用koa构建的):

当前域属于 http://localhost:3000,咱们在页面上这请求

<body>
  <script>
    var script = document.createElement('script')
    script.src = 'http://localhost:4000/jsonp/run'
    script.async = true
    document.body.appendChild(script)
  </script>
</body>

http://localhost:4000/jsonp/run 中,咱们返回了一段打印状态的script

var valForServerB = 'a'
router.get('/jsonp/run', (ctx) => {
  let script = `
    alert('我来自服务器b,个人值是${valForServerB}')
  `
  ctx.body = script
})

这样,咱们能够在当前页面上显示 valForServerB 的值了。

几种类型

根据 JSONP 返回的代码片断不一样,混入本身的情感,我将 JSONP 分为三种类型(这种带着情感的划分,须要各位大牛的指正):

  • 返回执行
    返回代码即执行代码,直接在页面上产生效果

  • 返回定义
    返回代码是函数的定义,具体调用时机交给当前页面决定

  • 返回调用
    函数的执行过程是在页面上所定义的,JSONP的返回只是函数的调用,固然包含传给函数的参数。

为了保持当前页面的的绝对控制权,返回调用应该是应用最广的

错误处理

JSONP使用过程当中,会有两种常见错误:

  • 请求失败或服务器返回失败
    捕获此类错误,咱们是借用 script 的 onerror 处理

  • 服务器返回内容错误
    针对这类错误,咱们会在当前页面借用定时器去处理。在返回调用时,咱们能够在页面上的函数定义中埋下时间因子;在返回定义时,咱们能够设置时间点去检测指望调用的方法是否存在。固然,此方法会由于网络等因素变得不可靠。

CORS(跨域资源共享)

CORS是当前页面与其余域执行的一种双方约束,须要浏览器应用和服务器程序之间的协调。

咱们在服务器端能够经过设置CORS响应头部:

  • Access-Control-Allow-Origin: <origin> | *
    容许访问的源

  • Access-Control-Allow-Methods
    容许访问的方法

  • Access-Control-Allow-Headers
    运行添加的请求头部

  • Access-Control-Expose-Headers
    容许客户端能够访问的头部

  • Access-Control-Max-Age
    预请求的缓存周期

  • Access-Control-Allow-Credentials
    是否运行请求加入用户凭证信息

相应的,在请求头部中,咱们能够加入:

  • Origin
    告知服务器请求的源

  • Access-Control-Request-Method
    告知服务器使用请求的的方法

  • Access-Control-Request-Headers
    告知服务器,请求中携带的头部

结语

跨域请求好,安全第一位。在咱们跨域请求时,咱们要确保咱们请求的服务器返回的数据是可信任的。

相关连接

cross-origin-resolve-demo

MDN CORS

相关文章
相关标签/搜索