用生命谱写代码的赞歌

0%

jsonp 跨域访问原理

JS 跨域

JS 跨域是指通过 JS 在不同的域之间进行数据传输或通信,比如用 Ajax 向一个不同的域请求数据,或者通过 JS 获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

同源策略

同源策略是浏览器的一种安全策略,所谓同源是指域名,协议,端口号完全相同。

  1. 目的
    • 保护用户信息安全
    • 假如你的支付宝已经登录了,域名是 a.com ,有一个黑客在自己的页面上(域名是 b.com )写了一段让你向他的支付宝转账的脚本,如果没有浏览器同源策略,后果无法想象!!!
  2. 限制
    • cookie、localStorage、IndexDB无法读取
    • 无法操作跨域的 iframe 里面的 DOM 元素
    • Ajax 请求无法发送

何为跨域

不同源则为跨域,假设当前域名是 http://www.example.com/detail.html ,其中 com 是顶级域名, example 是一级域名, www 是特殊的二级域名。

1
2
3
4
5
6
7
http://api.example.com/detail.html         不同源   域名不同
https//www.example.com/detail.html 不同源 协议不同
http://www.example.com:8080/detail.html 不同源 端口不同
http://api.example.com:8080/detail.html 不同源 域名、端口不同
https://api.example.com/detail.html 不同源 协议、域名不同
https://www.example.com:8080/detail.html 不同源 端口、协议不同
http://www.example.com/detail/index.html 同源 只是目录不同

为什么不能跨域?

出于安全考虑,浏览器禁止跨域访问。

跨域的方式

目前主流跨域方式有以下几种:

  1. jsonp
  2. cors
  3. 降域
  4. postMessage
  5. 后端代理

jsonp 跨域访问了,还安全吗?

安全不安全是对于服务器而言,你发送了 callback 参数,服务器不返回也就没有了作用, jsonp 是浏览器与服务器双方配合才能实现。所以是安全的。

jsonp 跨域原理

在 js 中,我们直接用 XMLHttpRequest 请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的 js 脚本文件却是可以的, jsonp 正是利用这个特性来实现的。

比如,我们有个 index.html 页面,它内部需要通过 Ajax 获取不同域上的 json 数据,假设这个 json 数据的服务器地址是 http://example.com/json.php ,那么 index.html 中的代码可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
<script>
function getData(data) {
console.log(data)
}
</script>
<script>
var script =document.createElement('script')
//调用来自example.com下的接口
script.src="http://example.com/json.php?callback=getData"
document.head.appendChild(script);
document.head.removeChild(script);
</script>

我们可以看到获取数据的地址后面有一个 callback 参数,这个参数可以修改,但是必须保证与请求服务器接口的 callback 参数一致,以便服务器正确解析。如果获取数据的服务器接口不是你自己控制的,就必须按照提供数据的那一方的规定格式来操作,一般习惯都是 callback

因为获取数据的地址被当做一个 js 文件引入,所以必须返回一个能执行的 js 文件,所以 json.php 代码可能是这样的:

1
2
3
4
5
6
<?php
$callback = $_GET['callback']; // 得到回调函数名称
$arr = array("name"=>"xiaoming", "age"=>18); // 需要返回的数据
$result = json_encode($arr); // 将数组转为json格式 {"name": "xiaoming", "age": 10}
echo $callback.'('.$result.')'; // 返回数据
>

最终 index.html 页面输出结果为:

getData({"name": "xiaoming", "age": 10})

所以通过 http://example.com/json.php?callback=getData 得到的 js 文件,就是我们之前定义的 getData 函数,并且它的参数就是我们需要的 json 数据,这样我们就跨域获得了我们需要的数据。

简单来说, jsonp 的原理就是通过 script 标签引入一个 js 文件,这个 js 文件载入成功后会执行我们在 url 参数中指定的函数,并且会把我们需要的 json 数据作为参数传入。所以 jsonp 是需要服务器端的页面进行相应的配合的。