关于javascript:常见跨域解决办法及实现原理一JSONP

41次阅读

共计 1773 个字符,预计需要花费 5 分钟才能阅读完成。

一、什么是跨域?

当协定、(主 / 子)域名、端口号中任意一个不雷同时,都算作不同域,不同域之间相互申请资源,就称为跨域

1、什么是同源策略及其限度内容?

同源策略是一种约定,是指 协定、域名、端口 三者雷同,即使两个不同域名指向同一个 ip 地址,也非同源。

限度内容:

  • 同源策略限度内容有:Cookie、localStorage、IndexedDB
  • DOM 节点
  • AJAX 申请
  • 但 img、link、script 这个三个标签是容许跨域加载资源的

2、常见跨域场景

特地阐明:

  • 如果是因为协定和端口造成的跨域问题,“前台”是无能为力的。
  • 判断是否跨域,仅仅是通过 url 比照来辨认的,并不会比照 url 对应的 ip 地址。
  • 当咱们申请服务器数据呈现跨域时,申请是能够失常收回的,服务端也能够收到返回后果,只是被浏览器拦挡了申请后果。

跨域解决办法

1、jsonp(原理及优缺点如下)

  • 受同源策略的影响,ajax 不容许进行跨域申请, 但 <script> 标签的 src 属性没有跨域限度,利用该个性,能够从其余跨域的 url 中获取的 json 数据,
  • 长处:JSONP 兼容性较好,可用于解决支流浏览器的跨域问题,并且不须要 XMLHttpRequest 或 ActiveX 的反对,可能间接拜访响应文本,反对在浏览器与服务器之间双向通信。
  • 毛病:仅反对 get 办法,具备局限性,存在平安问题,例如:被歹意注入代码、蒙受 xss 攻打

2、JSONP 实现过程

  • 在 js 中,咱们尽管不能间接用 XMLHttpRequest 申请不同域上的数据,但在页面上引入不同域的 js 文件是能够的,JSONP 正是利用这一个性来实现的。
  • JSONP 由两局部组成:回调函数和数据,回调函数是当响应到来时,应该在页面中调用的函数,而数据是传入回调函数中的 JSON 数据。
  • 创立一个 <script> 标签,将须要跨域拜访的接口地址赋值给 src, 并在该地址中向服务器传递函数名(能够应用?callback=XX 函数名),
  • 服务器接管到申请后,把传递进来的函数名和它须要给你的数据拼接成一个字符串, 例如:传递进去的函数名是 show,它筹备好的数据是 show(‘ 我不爱你 ’)。
  • 最初服务器把筹备的数据通过 HTTP 协定返回给客户端,客户端再调用执行之前申明的回调函数(show),对返回的数据进行操作。

3、封装实现

在开发中可能会遇到多个 JSONP 申请的回调函数名是雷同的,这时候就须要本人封装一个 JSONP 函数。

首先建一个启动本地服务的 js, 通过 node 启动后,即可拜访 http://localhost:3000 本地服务
// server.js
let express = require('express')
let app = express()
app.get('/say', function(req, res) {let { wd, callback} = req.query
  console.log(wd) // Iloveyou
  console.log(callback) // show
  res.end(`${callback}('我不爱你')`)
})
app.listen(3000)
而后在 index.html 中的 script 标签内运行该处代码
function jsonp({url, params, callback}) {return new Promise((resolve, reject) => {let script = document.createElement('script')
    window[callback] = function(data) {resolve(data)
      document.body.removeChild(script)
    }
    params = {...params, callback} // wd=b&callback=show
    let arrs = []
    for (let key in params) {arrs.push(`${key}=${params[key]}`)
    }
    script.src = `${url}?${arrs.join('&')}`
    document.body.appendChild(script)
  })
}
jsonp({
  url: 'http://localhost:3000/say',
  params: {wd: 'Iloveyou'},
  callback: 'show'
}).then(data => {console.log(data)
})

正文完
 0