1

一、什么是跨域?

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

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

同源策略是一种约定,是指 协议、域名、端口 三者相同,即便两个不同域名指向同一个ip地址,也非同源。
image.png

限制内容:

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

2、常见跨域场景

image.png

特别说明:

  • 如果是因为协议和端口造成的跨域问题,“前台”是无能为力的。
  • 判断是否跨域,仅仅是通过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)
})

茴香
34 声望1 粉丝

好好学习,天天向上