同源策略是从安全性的角度考虑浏览器的,所谓的同源是指请求的URL地址中的协议、域名、端口都相同,只要有其中一个不相同就是跨域。
比如:
http://www.example.com/detail.html
调用http://api.example.com/detail.html (api 域名不同)
调用https://www.example.com/detail.html (https 协议不同)
调用http://www.example.com:8080/detail.html (:8080端口不同)
解决方法:
- jsonp
- document.domain+iframe
- location.hash+iframe
- window.name+iframe
- window.postMessage
- flash等第三方插件
JSONP原理
静态script标签的src属性进行跨域请求
<script /*async*/ type="text/javascript" src="http://tweb.com/data.php?flag=1">
<script type="text/javascript">
/*
script标签里面的async属性表示异步加载资源,默认情况下是同步加载
这种方式存在的两个主要的问题:
1、必须保证加载的顺序
2、不方便通过程序传递参数
*/
console.log(data);
console.log(data.username);
console.log(data.password);
</script>
动态创建script标签
jsonp的本质:动态创建script标签,然后通过他的src属性发送跨域请求,然后服务器端响应的数据格式为【函数调用(foo(实参))】,所以在发送请求之前必须先声明一个函数,并且函数的名字与参数中传递的名字要一致,这里声明的函数也是由服务器响应的内容来调用。
<script type="text/javascript">
/*
hello就是回调函数
这就是jsonp的本质:动态创建script标签,然后通过他的src属性发送跨域请求,然后服务器端响应的数据格式为【函数调用(foo(实参))】
所以在发送请求之前必须先声明一个函数,并且函数的名字与参数中传递的名字要一致,这里声明的函数也是由服务器响应的内容(实际上就是一段js代码)来调用
*/
var script = document.createElement('script');
script.src = 'http://tweb.com/data.php?callback=hello&username=zhangsan&password=123456';
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
function hello(data) {
console.log(data);
}
jquery演示JSONP获取跨域的数据
<script type="text/javascript" src="./jquery.js"></script>
<script type="text/javascript">
$(function () {
$('#btn').click(function () {
$.ajax({
type: 'get',
url: 'http://tweb.com/jsonp.php',
dataType: 'jsonp',
jsonp: 'cb', //jsonp属性作用自定义参数名字callback=abc 名字指的是等号前面的键,后端根据键获取方法名
// jquery获取的参数名默认callback
jsonpCallback: 'abc',// 这个属性的作用就是自定义回调函数的名字callback=abc 指的是等号后边的值
data: {},
success: function (data) {
console.log(data.username);
console.log(data.password);
},
error: function (data) {
console.dir(data);
console.log('error');
}
})
})
})
</script>