JSONP|JSONP 跨域

一、什么是同源策略? 同源策略限制从一个源加载的文档或者脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。非同一个源的定义:

  1. 不同协议,https 和 http,如 https://www.baidu.com 和 http://www.baidu.com
  2. 不同端口,如 http://127.0.0.1:8080 和 http://127.0.0.1:8090
  3. 不同域名,如 a.com 和 b.com
参考:浏览器的同源策略 | MDN
二、什么是跨域?跨域有几种实现形式? 跨域就是不同源的资源之间的交互。正是因为同源策略,才会出现跨域这种问题。跨域的实现方式有:
  1. JSONP
  2. CORS
  3. 降域
  4. postMessage
三、JSONP 的原理是什么 利用 html 的 script 标签可以引入其他 JS 资源而且不引起跨域问题,原理是 JS 是被下载到当前浏览器环境执行,所以就不算跨域,就像平常通过 cdn 引入 jQuery 一样。因此,我们可以通过这种方式,让后端返回数据,具体流程如下:
  1. 定义数据处理函数 _fun
  2. 创建 script 标签,src 的地址执行后端接口,最后加个参数 callback = _fun
  3. 服务端在收到请求后,解析参数,计算返还数据,输出 fun(data) 字符串。
  4. fun(data) 会放到 script 标签做为 js 执行。此时会调用 fun 函数,将 data 做为参数。
四、CORS 是什么? CORS(Cross-Origin Resource Sharing)跨域资源共享,是一种允许 Web 应用服务器进行跨域访问控制机制,从而使跨域数据传输得以安全进行。具体通过在响应头的 Header 里面加上 Access-Control-Allow-Origin属性,允许相应的源地址访问来实现。
五、演示三种以上跨域的解决方式 1. JSONP
通过 node + express 来搭建本地服务器,实现 JSONP 效果。 JS 代码:
JSONP 演示 - 锐客网 数据展示

服务端代码
const express = require('express') const Mock = require('mockjs') const router = express.Router()router.use('/', (req, res, next) => { console.log('jsonp') next() })router.get('/', (req, res, next) => { const data = https://www.it610.com/article/Mock.mock({'list|1-10': [{ 'id|+1': 1, 'name|1-3': '@FIRST' }] }) const callback = req.query.callback const resData = https://www.it610.com/article/`${callback}(${JSON.stringify(data)})` res.end(resData) })module.exports = router

实际演示
可以看到这请求和相应不是同源的,因为端口不同。

JSONP|JSONP 跨域
文章图片
JSONP 演示 2.CORS
客户端代码
CORS 演示 - 锐客网 数据展示

服务端代码
const express = require('express') const router = express.Router() const Mock = require('mockjs')router.use('/', (req, res, next) => { console.log('cors')res.append('access-control-allow-origin', 'http://127.0.0.1:8090') // res.append('withCredentials', true) next() })router.get('/', (req, res, next) => { const data = https://www.it610.com/article/Mock.mock({'list|1-10': [{ 'id|+1': 1, 'name|1-3': '@FIRST' }] }) res.json(data) })module.exports = router

实际演示
JSONP|JSONP 跨域
文章图片
CORS 演示 3. 降域
假设现在我有两个域名 a.sub.com 和 b.sub.com,但实际上指向的是同一个 ip 地址和 端口,尽管如此,因为域名不同,依旧是非同源,为了解决这个问题,通过window.domain来降域,解决跨域问题。
修改 hosts 文件

JSONP|JSONP 跨域
文章图片
修改 hosts 两个 html 文件,里边使用 iframe 演示。
网站 a - 锐客网iframe { background-color: #eee; } 使用降域实现跨域

网站 b.com - 锐客网 这是网站 b

在未使用window.domain降域之前,在网站 a 里是无法访问网站 b 的节点的,如下:

JSONP|JSONP 跨域
文章图片
为降域,获取节点失败
而加上之后:
JSONP|JSONP 跨域
文章图片
降域成功演示
【JSONP|JSONP 跨域】全部代码地址 | GitHub

    推荐阅读