1.同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
现在所有的浏览器都支持同源策略
在前端工作中,会经常遇到跨域问题(同源策略问题),所谓同源,就是同协议,同域名,同端口
协议:http https
域名:每一个网站都有自己的服务器,每一个服务器都有一个ip地址,每一个ip地址都会指向一个域名,域名有一级域名,二级域名和三级域名
http://aa(三级域名).aa(二级域名).com(一级域名)越往后范围越大
js中的同源,也就是协议,域名和端口都一致的时候,可以相互使用资源接口,因为他们是同源,否则就会有跨域问题
1.协议不同
http://www.baidu.com
https://www.baidu.com
2.域名不同
http://www.baidu.com
http://www.sian.com
3.端口不同
http://www.baidu.com:8080
http://www.baidu.com:5500
只有js才会考虑同源问题(<script>)
img video audio 等标签加载的时候不用考虑同源问题
但是浏览器设置了一些权限,标签也不能随意跨域
2.js怎么实现跨域
1.jsonp
2.在服务器端,设置 CORS 跨域资源共享
3.document.domain
4.html5的新增方法,postMessage方法,向不同源的页面发送信息
1.jsonp
1.创建script标签
2.在创建的标签添加src=接口地址,该接口地址就是需要跨域的地址,需要注意的是必须在路径上添加一个成功后的回调函数,另外要保证当前页面中有这个函数
3.把script标签放到body中
4.删除该script标签
//前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jsonp</title>
</head>
<body>
<input type="text" value="" id="txt"><br>
<button id="btn">点击</button>
<button id="btn2">点击cors</button>
<hr>
<p id="msg"></p>
</body>
<script src="./js/jquery.js"></script>
<script type="text/javascript">
let btn=document.querySelector('#btn');
let txt=document.querySelector('#txt');
let msg=document.querySelector('#msg');
btn.οnclick=function(){
let val=txt.value;
// 创建script标签
let ele=document.createElement('script');
// 添加src
ele.src='http://127.0.0.1/php/23jsonp.php?val='+val+'&cb=aa';//添加数据 val 和 回调函数aa
//把script放在body中
document.body.appendChild(ele);
//删除script
document.body.removeChild(ele);
}
function aa(str) {
msg.innerHTML=str;
}
$('#btn2').click(function() {
$.ajax({
type:'get',
data:{val:$('#txt').val()},
url:'http://127.0.0.1/php/24cors.php',
success(data){
console.log(data);
msg.innerHTML=data;
}
})
})
</script>
</html>
//后端23jsonp.php
<?php
$val=$_GET['val'];
$str=$val.'醉里挑灯看剑';
$cb=$_GET['cb'];
echo $cb.'("'.$str.'")';
?>
2.CORS 设置跨域
在服务器接口页面设置==header(‘Access-Control-Allow-Origin:*’);==即可访问,安全性差
<?php
//CORS 设置跨域
header('Access-Control-Allow-Origin:*');
$val=$_GET['val'];
$str=$val.'醉里挑灯看剑';
echo $str;
3.postMessage
在A页面中访问B页面中的元素
如果是同源页面,则可以直接访问
如果是不非同源页面,显示是没有问题的,但是要在a页面中操作b页面,则需要解决跨域问题
方法:主要是A页面设置 win.contentWindow.postMessage(‘haha’, ‘http://127.0.0.1’);
B页面添加信息事件监听window.addEventListener(‘message’, () => { if (event.data == ‘haha’) {} })
//A页面内部访问修改B页面内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>posA</title>
<style type="text/css">
.bor {
border: 1px #f00 solid;
width: 500px;
height: 500px;
}
</style>
</head>
<body>
<h1>A页面</h1>
<iframe src="http://127.0.0.1/php/25posB.html" frameborder="0" class="bor" id="win"></iframe>
<button id="btn">点击</button>
</body>
<script type="text/javascript">
let btn = document.querySelector('#btn');
let win = document.querySelector('#win');
btn.onclick = function () {
// 往b页面的window中提交信息,第一个参数是提交的信息,第二个参数是b页面所在的域
win.contentWindow.postMessage('haha', 'http://127.0.0.1');
}
</script>
</html>
//b页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>posB</title>
</head>
<body>
<h1>B页面</h1>
<p id="aa">
万万没想到,啦啦啦
</p>
</body>
<script type="text/javascript">
window.addEventListener('message', () => {
// event 表示事件对象
/*
event.data页面传过来的内容
event.target 当前页面的window对象
event.srcElement 消息源页面的window对象
*/
// console.log(event.data);
// console.log(event.target);
// console.log(event.srcElement);
if (event.data == 'haha') {
let p = document.getElementById('aa');
p.style.fontSize = '30px';
p.style.color = '#04be02';
}
});
</script>
</html>
4.jq中的jsonp
参数
{
url 跨域访问的接口
data 要提交的数据
dataType 数据类型 jsonp
jsonp 要传给后台的函数的键名
jsonpCallback 要传给后台的函数名(也可以不写,直接是success函数)
success 成功后的回调
}
ex:
$('#btn').click(function() {
$.ajax({
type:'get',
data:{val:$('#txt').val()},
dataType:'jsonp',
jsonp:'cb',
url:'http://127.0.0.1/php/23jsonp.php',
// jsonpCallback:'aa',
success(data){
$('#msg').text(data);
console.log('success:'+data);
}
})
})
function aa(data) {
// $('#msg').text(data);
console.log('aa:'+data);
}
<?php
$val=$_GET['val'];
$str=$val.'醉里挑灯看剑';
$cb=$_GET['cb'];
echo $cb.'("'.$str.'")';
?>
5.async和await
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>async和await</title>
</head>
<body>
</body>
<script src="./js/jquery.js"></script>
<script type="text/javascript">
/*
async 函数关键字,它修饰的函数,返回一个promise对象
ansyc 函数可以通过then方法获取函数的返回值
一个单独的async的函数,实际上和一个promise实例是一样的
*/
async function aa() {
return '天涯何处无芳草';
}
let p=aa();
console.log(p);
p.then(data=>{
console.log(data);
})
/*
await(async wait:异步等待),它等待的是一个promise,所以await后面需要跟一个promise对象
await 必须放在async函数中才能使用
*/
function setData(type,url,data) {
return new Promise((resolve,reject)=>{
$.ajax({
type:type,
url:url,
data:data,
success(data){
resolve(data);
},
error(err){
reject(err);
}
});
})
}
async function show() {
console.log('开始');
let a=await setData('post','promise.php',{name:'郭德纲'});
console.log(a);
/*
如果await后面跟的不是一个promise对象,那么他会先转化成一个 立即执行resolve方法的promise,也就是把await后面的内容,当成一个成功的结果进行调用
*/
let n=await 100;
console.log(n);
let m=await n+100;
console.log(m);
let b=await setData('post','promise.php',{name:'于谦'});
console.log(b);
}
show();
/*
简单总结
async不会造成代码的阻塞,但是,await会造成async内部的代码阻塞
*/
// function run() {
// console.log('春江花月夜');
// let b=await setData('post','promise.php',{name:'于谦'});
// console.log(b);
// }
// run();
/*
await 后面的promise对象,也有可能返回 reject,如果一个await返回的是reject,那么整个async函数都会被中断
可以使用 try..catch 语句来封装多个 await
*/
async function see() {
try {//执行正确的代码
console.log('开始');
let a=await setData('post','promise.php',{name:'春伟 '});
console.log(a);
let err=await Promise.reject('错错错');
console.log(err);
let m=await 200;
console.log(m);
} catch (error) {
//执行错误的操作
console.log(error+'摸摸摸');
}
}
see();
</script>
</html>