跨域

116 阅读3分钟

一、同源策略

1、源

  • 源=协议+域名+端口号

2、同源

3、同源策略

  1. 浏览器规定:若JS运行在源A里,那么就只能获取源A的数据,不能获取源B的,即不允许跨域
  2. 举例:frank.com/index.html 引用了 cdn.com/1.js ,即1.js运行在frank.com里,与cdn.com无关,只是1.js从cdn.com处下载,所以,1.js只能获取frank.com的数据
  3. 为什么要有同源策略:保护用户隐私。总而言之,不同源的页面之间,不准互相访问数据

4、实操理解跨域

需提前自己做两个网站来模拟正常网页(qq.com)和黑客网页(lanlan.com)

  1. 在qq.com:8888里运行的JS可以访问/friends.json(正常使用AJAX)
  2. 在lanlan.com:9999里运行的JS不可以访问(黑客偷数据)
  3. 黑客的请求成功发送,但未成功拿到响应

5、一些答疑

  1. a.qq.com访问qq.com也算跨域?why
  • 历史上,出现过不同公司公用域名,a.qq.com和qq.com不一定是同一个公司
  1. 不同端口也算跨域?why
  • 同上,不同端口不一定是同一个公司
  1. 两个网站IP一样也是跨域?why
  • 同上,IP可以不同公司共用
  1. 那为什么可以跨域使用如CSS、JS、图片等
  • 同源策略限制的是数据访问,引用CSS、JS、图片时,并不知道其具体内容,只是引用

二、如何跨域

1、CORS

Crose-Origin Resource Sharing,跨源资源共享

  1. 如果要共享数据,需提前申明
  2. 在对应的响应头里写lanlan.com可以访问
  3. response.setHeader("Access-Control-Allow-Origin","http://lanlan.com:9999")

2、JSONP

  • IE6 7 8 9不支持CORS,要兼容IE,可以使用JSONP
  • 理解JSONP:我们可以引用JS,那么就让JS包含JSON的数据即可,可以理解为P是包含之意
  • 但不一定非得是JSON,也可以是XML等,只是命名为JSONP而已(注意:JSON和JSONP完全不相干)
2.1、操作步骤
  1. 新建friends.js,将JSON数据写进该JS里
else if(path==="/friends.js"){
    const string=fs.readFileSync("./public/friends.js").toString(); //拿到JS内容
    const data=fs.readFileSync("./public/friends.json").toString(); //拿到JSON数据
    const string2=string.replace("{{data}}",data); //将数据填入JS内容里
}
  1. lanlan.com用script标签引用/friends.js
const script=document.createElement('script')
script.src='http://qq.com:8888/friends.js'
document.body.appendChild(script)
script.onload=()=>{
    script.remove() //为防止script堆积,用完即删
}
  1. friends.js执行lanlan.com事先定义好的window.xxx函数(回调)
window.xxx=(data)=>{
    console.log(data)
}
window.xxx=({{data}}) //lanlan.com就通过window.xxx获取到了数据
2.1.1、优化
  1. JSONP如何做到定向分享(即只有lanlan.com能访问qq.com,lanlan2.com不能)。加个判断
else if(path==="/friends.js"){
    if(request.headers["referer"].indexOf("http://lanlan.com:9999")===0){
        ...
    }else{
        response.statusCode=404
        response.end()
    }
}
  1. xxx可以不写死吗?因为有时xxx会被占用。可以,只要lanlan.com定义的函数名和qq.com/friends.js 执行的函数名是同一个即可,如可用随机数做函数名
const random='lanlanJSONPCallbackName'+Math.random()
window[random]=(data)=>{
    console.log(data)
}
...
script.src=`http://qq.com:8888/friends.js?callback=${random}`
//在qq.com的server.js里将该随机函数名也填入string2里
2.2、封装JSONP

微信图片_20230601200324.png

2.3、关于JSONP
  1. JSONP是什么?
  • 在跨域时,由于当前浏览器不支持CORS,此时需要另一种方式来跨域;即请求一个JS文件,该文件会执行一个回调,回调里就有我们要的数据
  1. 该回调的名字是?
  • 名字是可以随机生成的(用随机数),把这个名字以callback参数传给后台,后台会返回给我们并执行
  1. JSONP的优点是?
  • 能兼容IE,可以跨域
  1. JSONP的缺点是?
  • 由于它是script标签,读不到如AJAX那样精确的状态(如状态码),只知道是成功还是失败
  • script只能发get请求(即JSONP不支持post)