1.同源策略
同源策略,是由网景(netscape)提出的一个著名的安全策略,现在所有的浏览器都会使用这一安全策略。所谓同源策略,即相互访问的页面之间必须具有相同的协议、端口和主机地址。
由于同源策略的限制,不同域名之间无法通过HTTP请求相互访问。我们把不同域名之间的访问问题称为跨域问题。
2.跨域访问
1.什么是跨域
跨域是指跨域名的访问,以下情况都属于跨域:
跨域原因说明 | 示例 |
---|---|
域名不同 | www.jd.com 与 www.taobao.com |
域名相同,端口不同 | www.jd.com:8080 与 www.jd.com:8081 |
二级域名不同 | item.jd.com 与 miaosha.jd.com |
协议不同 | http://与https:// |
2.为什么有跨域问题?
跨域不一定会有跨域问题。
因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是于当前页同域名的路径,这能有效的阻止跨站攻击。
因此:跨域问题 是针对ajax的一种限制。
但是这却给我们的开发带来了不变,而且在实际生产环境中,肯定会有很多台服务器之间交互,地址和端口都可能不同,怎么办?
3.解决跨域问题的方案
3.1静态
举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="http://node.com/jsonp/jsonp.php"></script>
<script>
window.onload=function(){
var btn=document.getElementById("btn");
btn.addEventListener("click",function(){
console.log(data)
})
}
</script>
</head>
<body>
<button id="btn">点击</button>
</body>
</html>
<?php
echo "var data = {'username':'lisi'}";
?>
注意: php返回数据时,将变量名以字符串的方式返回,在js中会自动解析
3.2动态
举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload=function(){
var script=document.createElement("script");
script.src="http://node.com/jsonp/jsonp.php";
var head=document.getElementsByTagName("head")[0];
head.appendChild(script);
var btn=document.getElementById("btn");
btn.addEventListener("click",function(){
console.log(data)
})
}
</script>
</head>
<body>
<button id="btn">点击</button>
</body>
</html>
<?php
echo "var data = {'username':'lisi'}";
?>
3.3jsonp
JSONP(JSON with Padding)可用于解决主流浏览器的跨域数据访问的问题)。跟JSON没有关系。
JSONP是如何实现跨域访问的?本质上是利用HTML元素的src属性都可以跨域的思路来解决的。
jsonp.php代码:
<?php
$callback=$_GET["callback"];
$name=$_GET["username"];
$pwd=$_GET["pwd"];
echo $callback.'('.'{"username":"'.$name.'","pwd":"'.$pwd.'"}'.')';
?>
客户端实现 callbackFunction 函数:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 实例</title>
</head>
<body>
<div id="divCustomers"></div>
<script type="text/javascript">
function callbackFunction(result, methodName)
{
var html = '<ul>';
for(var i = 0; i < result.length; i++)
{
html += '<li>' + result[i] + '</li>';
}
html += '</ul>';
document.getElementById('divCustomers').innerHTML = html;
}
</script>
<script type="text/javascript" src="https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction"></script>
</body>
</html>
在这里,我们对函数进行封装:
function json(obj){
var defaults={
type:"get",
url:"",
data:{},
dataType:"jsonp",
jsonp:"callback",
success:function(data){
console.log(data);
}
}
for(var key in obj){
defaults[key]=obj[key]
};
//回调函数名
var cbName="jQuery"+("1.11.1"+Math.random()).replace(/\d/g,"")+"_"+(new Date().getTime());
//判断是否传回调函数的名
if(defaults.jsonpCallback){
cbName=defaults.jsonpCallback;
}
window[cbName]=function(data){
defaults.success(data);
}
//数据拼接
var param="";
for(var attr in defaults.data){
param+="&"+attr+"="+defaults.data[attr];
}
//动态
var script=document.createElement("script");
script.src=defaults.url+"?"+defaults.jsonp+"="+cbName+param;
var head=document.getElementsByTagName("head")[0];
head.appendChild(script);
}
封装后,在html页面可以直接进行调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="json.js"></script>
<script>
$(function(){
$("#btn").click(function(){
json({
type:"get",
url:"http://node.com/jsonp/jsonp2.php",
data:{username:"admin",pwd:"123"},
dataType:"jsonp",
jsonp:"callback",
jsonpCallback:"callbackFunction",
success:function(data){
console.log(data)
}
})
})
})
</script>
</head>
<body>
<button id="btn">点击</button>
</body>
</html>
拓展:jQuery 使用 JSONP
我们可以直接调用jquery中的getJSON()方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
$(function(){
$("#btn").click(function(){
$.getJSON("http://node.com/jsonp/jsonp.php?callBack=?",function(data){
console.log(data)
})
})
})
</script>
</head>
<body>
<button id="btn">点击</button>
</body>
</html>
通过这个方法,我们也可以实现跨域功能