跨域、CORS、JSONP

163 阅读3分钟

跨域关键知识

同源策略

  • 浏览器故意设计的一个功能限制

CORS

  • 突破浏览器限制的一个方法

JSOPN

  • IE时代的妥协

同源策略(不同源的页面之间,不准互相访问数据)

同源定义

  • window.origin 或 location.origin 可以得到当前源

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

  • 如果两个 url 的协议、域名、端口号完全一致,那么这两个 url 就是同源的。

  • 举例:qq.com、https://www.baidu.… 不同源;baidu.com、https://www.baidu.… 不同源,完全一致才算同源。

同源策略定义

浏览器规定

  • 如果 JS 运行在源 A 里,那么就只能获取源 A 的数据

  • 不能获取源 B 的数据,即不允许跨域

  • 举例:(省略 http 协议),假设 frank.com/index.html 引用了 cdn.com/1.js ,那么就说「 1.js 运行在源 frank.com 里」,注意这跟 cdn.com 没有关系,虽然 1.js 从它那下载,所以 1.js 就只能获取 frank.com 的数据,不能获取 1.frank.com 或者 qq.com 的数据

1.png

问题的根源

无法区分发送者

  • QQ 空间页面里的 JS 和黑客网页里的 JS

  • 发的请求几乎没有区别(referrer 有区别)

  • 如果后台开发者没有检查 referer,那么就完全没区别

  • 所以,没有同源策略,任何页面都能偷 QQ 空间的数据,甚至支付宝余额!

那检查 referer 不就好了?

  • 安全原则:安全链条的强度取决于最弱一环

  • 万一这个网站的后端开发工程师是个傻 X 呢

  • 所以浏览器应该主动预防这种偷数据的行为

  • 总之,浏览器为了用户隐私,设置了严格的同源策略

步骤

image.png

hosts

设置本地域名映射

  • qq.com 映射到 127.0.0.1

  • 就可以访问 http://qq.com:8888/index.html

  • frank.com 映射到 127.0.0.1

  • 就可以访问 http://frank.com:9999/index.html

如何设置 hosts

  • 需要用管理员权限操作,打开记事本,找到

image.png

跨域 AJAX

正常使用 AJAX

  • qq.com:8888 里运行的 JS 可以访问 /friends.json

黑客偷数据

  • frank.com:9999 里运行的 JS 不能访问!

  • 浏览器需要 CORS

  • 提问:黑客的请求发成功了没有?答:成功了,因为 qq.com 后台有 log。黑客拿到响应了没有?答:没有,因为浏览器不给数据给它

  • 注意:就没有浏览器不限制跨域么?如果不限制,就是浏览器 bug 了,快向浏览器反馈。

image.png

解决跨域的方法一: CORS

问题根源

  • 浏览器默认不同源之间不能互相访问数据

  • 但是 qq.comfrank.com 其实都是一个人的网站

  • 就是想要两个网站互相访问,浏览器为什么阻止

  • 好吧,用 CORS

  • 浏览器说,如果要共享数据,需要提前声明!

  • 哦,那怎么声明呢?

  • 浏览器说,qq.com 在响应头里写 frank.com 可以访问

  • 哦,具体语法呢?

  • Access-Control-Allow-Origin: http://foo.example

  • 浏览器说:都得文档里,去看 MDN 文档嘛

if (path === "/friends.json") {
    response.statusCode = 200;
    response.setHeader("Content-Type", "text/json;charset=utf-8");
    response.setHeader("Access-Control-Allow-Origin", "http://frank.com:9999");
    response.write(fs.readFileSync("./public/friends.json"));
    response.end();
  }

解决跨域的办法二:JSONP(兼容IE)

  • JSONP和JSON没有任何关系

步骤

image.png

image.png

image.png

image.png

JSON是什么(优缺点)

  • JSONP是我们在跨域的时候由于当前浏览器不支持CORS或者因为某些条件不支持CORS,我们必须使用另外一种方式来跨域,于是我们请求一个JS文件,这个JS文件会执行一个回调,回调里面就有我们的数据。回调的名字是随机生成的,一个随机数,然后把这个名字以 callback 的参数传给后台,后台会把这个函数返回给我们并执行。

JSONP的优点

  • 一、兼容IE;

  • 二、它可以跨域

JSONP的缺点

  • 一、由于它是script的标签,所以它读不到AJAX那么精确的状态(不知道状态码,不知道响应头,只知道成功或者失败);

  • 二、由于它是script标签,所以它只能发 get 请求,不能发 post 请求。