跨域

114 阅读1分钟

同源策略

同源策略(Same-Origin-Policy) 最早是由 Netscape 公司提出,是浏览器的一种安全策略。

即 不同源的页面之间,不准互相访问数据

  • window.origin 或 location.origin 可以得到当前源。
  • 同源:协议,域名,端口号,必须完全相同。
  • 违背同源策略就是跨域
  • ajax默认是遵循同源策略的。

举个栗子:

CORS 实现跨域

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

但是IE10以下是不支持的。

如何使用

因为CORS与AJAX没有什么差别,只不过浏览器发现是AJAX请求跨源,就会在请求中自动添加一些附加的头信息。因此我们只需要以此判断是否可以跨域,在响应头中加入一些信息即可。

所以,CORS跨域的关键是在服务器,只要服务器实现了CORS接口,即可跨源通信。

简单请求:

   response.setHeader('Access-Control-Allow-Origin', 'http://wangpf.com:9990')

注意:它的值要么是请求时Origin字段的值(协议 + 域名 + 端口),要么是一个*,表示接受任意域名的请求。

AJAX 和服务器代码展示:

http://wangpf.com:9990中的js内容:


const req = new XMLHttpRequest()
req.open('GET', 'http://qq.com:8888/friends.json')
req.send()
req.onreadystatechange = () => {
  if (req.readyState === 4) {
    if (req.status >= 200 && req.status < 300) {
      console.log(req.response);
    }
  }
}

http://qq.com:8888 中服务端内容

if(path === 'friends.json'){
  response.statusCode = 200
    response.setHeader('Content-Type', 'text/json;charset=utf-8')
    // console.log(request.headers['referer']); 
    response.setHeader('Access-Control-Allow-Origin', 'http://wangpf.com:9990')
    response.write(fs.readFileSync('./public/friends.json'))
    response.end()
  }

JSONP 实现跨域

什么是JSONP?

JSONP(JSONP with Padding) 是一大堆牛逼的程序员想出来的跨域方法。

当前网站创造一个script标签去请求另一个网站的JS,然后这个JS文件会夹带一些数据,这些数据会在我的网站上调用全局函数运行。

JSONP是怎么实现的?

因为我们当前浏览器或者某些条件不支持CORS来实现跨域,所以我们必须要使用另外一种方式来跨域,于是我们就请求JS文件,这个JS文件会执行一个回调,这个回调里面就有我们的数据。

这个回调名字是可以随机生成的,我们把这个随机数以callback为参数传给后台,后台会把这个函数再次返回给我们并执行

JSONP的优点和缺点

优点:

  • 支持IE
  • 可以跨域(好像是废话哦。。。)

缺点:

  • 由于它是script标签,它不能像AJAX一样,读出(拿到)状态码和响应头,它只知道成功和失败(用onload和onerror来监听)。
  • 由于它是script标签,它只能发get请求,不支持POST。 JSONP的原理
  • 网页有一些标签天生具有跨域的能力,比如:img link iframe script
  • JSONP 就是利用 script标签的跨域能力来发送请求的(这也是jsonp跨域只能用get请求的原因所在

封装一个JSONP函数

//封装JSONP函数  使用JSONP 实现
function JSONP(url) {
  return new Promise((resolve, reject) => {
    const random = 'WangpfCallbackName' + Math.random()
    window[random] = (data) => {
      resolve(data)
    }
    const script = document.createElement('script')
    script.src = `${url}?callback=${random}`
    document.body.appendChild(script)
    script.onload = () => {
      script.remove()
    }
    script.onerror = () => {
      reject()
    }
  })
}

JSONP('http://qq.com:8888/friends.js')
  .then((data) => {
    console.log(data);
  })