浏览器同源策略
浮动框架 前端7.8年前使用的技术
<iframe src="http://www.jd.com" frameborder="0"></iframe>
什么是浏览器的同源策略?
所谓同源: 就是同一个源 同一个来源 也就是两个网页在同一个环境下
我们尝试修改京东失败后 发现控制台很多警告
原因就是浏览器的同源策略:
如果两个网页是在一个源下面 那么浏览器不会阻止任何数据的互相交换以及更改
但是一旦两个网页不再同一个源 那么 浏览器直接就阻止了
* No 'Access-Control-Allow-Origin' header is present on the requested resource.
* 实际开发中 一旦遇到这个报错 那么就是涉及到跨域问题 要解决的
src所指向的地址 默认可以跨域并且拿到数据
<img src="https://www.baidu.com/img/bd_logo1.png" alt="">
原生js解决同源策略问题
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>原生js的jsonp跨域</h1>
<script>
function show(data) {
console.log("前端的show方法");
console.log(data);
}
function demo(data) {
console.log(data);
//渲染页面的代码
// h1.innerHTML=data;
}
// 这是服务器返回的格式
// demo({name:'小强',age:16,location:'文化大厦'})
</script>
<!--<script src="http://localhost/2019-11-25/php/04.crossData.php"></script>-->
<script src="http://localhost/2019-11-25/php/04.crossData.php?callback=demo"></script>
</body>
</html>
php
<?php
header('Content-type:text/html;charset=utf-8');
// echo "我是跨域服务器的数据,你跨过来了么?";
// 为了让前端的jsonp跨域能够执行的js代码
// echo "show('我是服务器的数据,通过方法传给前端!')";
$callback=$_GET["callback"];
echo $callback."({name:'小强',age:16,location:'文化大厦'})";
?>
JQ的jsonp解决同源策略
JQ的jsonp 只需要把dataType的值写上 jsonp就好了
html(下)php(同上)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>JQ的jsonp跨域请求</button>
<script src="jquery-1.11.1.js"></script>
<script>
/*
JQ的jsonp 只需要把dataType的值写上 jsonp就好了
*/
// JQ实现success方法 接收跨域服务器的数据原理:
/*function jQuery11110011546846705204228_1574655625550(data) {
ajax.success(data)
}*/
$("button").click(function () {
$.ajax({
url:"http://localhost/2019-11-25/php/04.crossData.php",
dataType:"jsonp",
success:function (data) {
console.log(data);
}
})
})
</script>
</body>
</html>
JQ的ajax跨域属性:
* crossDomain(一般不用)
* 如果jsonp跨域失败了 试试把这个属性加上
* corssDomain:true(强制跨域)
*
* jsonp:
* 修改callback键的
*
* jsonpCallback
* 修改callback值的 那个随机生成的方法名
function show(data) {
console.log("show方法也被调用:",data);
}
$("button").click(function () {
/*$.ajax({
url:"http://localhost/2019-11-28/php/01.jsonpData.php",
jsonp:"cb",
dataType:"jsonp",
jsonpCallback:"show",
success:function (data) {
console.log(data);
}
})*/
$.ajax({
url:"http://localhost/2019-11-28/php/01.jsonpData.php",
// jsonp:"cb",
dataType:"jsonp",
// type:"post",
// jsonpCallback:"show",
success:function (data) {
console.log(data);
}
})
})
Jcros跨域的请求
html
<script>
$("button").click(function () {
$.ajax({
url:"http://localhost/2019-11-28/php/02.crosData.php",
type:"post",
success:function (data) {
console.log(data);
}
})
})
</script>
php
<?php
header('Content-type:text/html;charset=utf-8');
// header("Access-Control-Allow-Origin:*");
// 允许指定域名下的所有页面来跨域
header("Access-Control-Allow-Origin:http://localhost:63342");
header("Access-Control-Allow-Method:GET,POST");
header("Access-Control-Max-Age:1000");
echo "服务器的数据,你跨域成功了么?";
?>
跨域说明
什么是跨域:
所谓跨域 就是两个不再同一个源下面的数据进行交互
交互双方已经沟通好 可以进行数据交互
但是由于 不同源 则默认被浏览器阻止下来
我们要解决这种问题
这就是跨域问题
具有src属性的标签:
img script embed iframe
script:src会尝试去请求一个js文件数据 并且把请求到的数据按照js代码解析并运行
处理方式:
1.利用src默认跨域的特点 实现原生js的jsonp跨域
原生js的jsonp跨域:
(1):定义script标签 把要跨域的服务器地址写到script标签的src里面
(2):我们看到网络请求有了 但是数据格式有点问题
返回的数据默认script标签按照js代码执行
那么我们能不能让服务器返回一个js格式的字符串
服务器返回一个js代码
返回一个方法调用
(3): 前端定义这个方法
(4):既然方法能被后台调用 那么能不能传个参数呢? 能!!!
(5):方法名最好不要是服务器自己定义
前端提交一个callback参数 值是当前前端自己定义的方法名
(6):服务器接收到callback 直接拼接一个 callback+"(参数)" 调用
总结:
第一步:把服务器地址写到script:src里面
第二步:手动拼接callback=本地自己定义的一个方法名
第三步:服务器$_GET["callback"] 接收callback参数
第四步:服务器echo 返回 方法名+"()" 字符串拼接
第五步: 并且在 方法名+"(给前端的参数)" 传入参数是给前端发送的数据
第六步:前端的自己定义的方法 用形参接收服务器返回的数据 实现jsonp跨域
2.JQ的json跨域
注意!!!!!!!!!!!!!!!!!!!!
只要是jsonp那么就需要服务器配合 写那个callback拼接那一堆
1.保证服务器符合jsonp跨域的要求
2.JQ的dataType:"jsonp" JQ会自动拼接callback参数
以上两个跨域(原生js的jsonp跨域和JQ的jsonp跨域) 都只能支持get方法
不可能支持post
// nginx代理跨域 现在知道一个名字就行了
cros跨域(服务器写的)
即支持get也支持post访问
No 'Access-Control-Allow-Origin' header is present on the requested resource.
这是跨域问题的错误提示 意思是:我们没有Access-Control-Allow-Origin这个头部信息
我们的访问时不被允许的
那么能不能让服务器有这个头部
cros跨域的设置:
服务器配置三个响应头就可以了
PHP的配置:
允许所有域名的服务器过来跨域
header("Access-Control-Allow-Origin:*")
(* 因为是允许所有人 所以有点不安全 还可以指明 指定域来跨域)
header("Access-Control-Allow-Origin:http://localhost:63342")
允许跨域的请求方式
header("Access-Control-Allow-Method:GET,POST")
跨域的缓存事件(没用 但是最好写上)
header("Access-Control-Max-Age:1000")