Skip to content

什么是跨域

一个源的下的文档或脚本去访问别的源的资源,这是因为浏览器的同源策略,不同源页面之间,不准互相访问数据。

  • 源=协议+域名+端口号(默认80端口不显示)
  • window.origin或localtion.origin可以得到当前源
  • 两个URL全部一致才为同源

同源策略

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

举例:如果JS运行在源A内,那么就只能获取源A的数据,不能获取源B的数据,即不允许跨源。

限制的是数据访问,但可以引用内容(css,js,图片)

解决办法

CORS(跨域资源共享)

举例:运行在 http://domain-a.com 的JavaScript代码使用XMLHttpRequest来发起一个到 https://domain-b.com/data.json 的请求。

步骤

若要共享数据,在共享网站的响应头里写允许那个网站可以访问

header(Access-Control-Allow-Origin:'url')

JSONP

为了跨域的时候某些浏览器不支持CORS(比如IE就不支持),必须使用另一种方法来跨域。

于是网站可以请求一个JS文件,JS会执行一个回调,回调里面有我们的数据。

回调名字可以是随机生成随机数,然后作为callback的参数传给后台,后台会把函数返回并执行。

步骤

  • A网站先将内容写到js内
  • B网站用script标签引用js
  • B网站事先定义window.xxx函数

window.xxx可以改些其他名字只要B网址定义的函数名和B网址里js执行的函数名是同一个

  • B网站引用js执行window.xxx通过这个可以获取到数据
  • 若script标签过多,可以删除
    script.onload = () => {
      script.remove();
    };
等script标签加载完后删除

优点

  • 兼容IE
  • 可以跨域

缺点

  • script标签读不到AJAX那么精确的状态(码和响应头),因为只用来监听onload和onerrfor
  • script标签只能发送get请求(JSONP不支持POST)

JSONP封装

jsonp的函数名约定俗称为callback

function jsonp(url){
  return new Promise((resolve,reject)=>{
  	const random = "JSONPCallbackName"+Math.random()
    window[random]=data=>{
      resolve(data)
    }
    const script = document.createElement("script")
    script.src = `${url}?callback=${random}`
    script.onload = ()=>{
    	script.remove()
    }
    script.onerror = ()=>{
    	reject()
    }
    document.body.appendChild(script)
  })
}

jsonp('http://lz.com:5050/friend.js').then(data=>{
	console.log(data)
})

在请求的时候可以通过headers["referer"]来判断是否同源

 if (path === "/friends.js") {
    if (request.headers["referer"].indexOf("http://lz.com:5050") === 0) {
      response.statusCode = 200;
      response.setHeader("Content-Type", "text/javascript;charset=utf-8");
      const string = `window['{{xxx}}']({{data}}) `
      const data = fs.readFileSync("./public/friends.json").toString();
      const string2 = string.replace("{{data}}", data).replace('{{xxx}}', query.callback);
      response.write(string2);
      response.end();
 }