同源策略:协议、域名和端口号都一致叫同域
为什么浏览器不支持跨域呢?
- cookie localstorage等等不支持跨域
- dom元素也有同源策略,比如iframe
- ajax不支持跨越
实现跨域:
- jsonp
- cors
- postMessage
- document.domain
- window.name
- location.hash
- http-proxy
- nginx
- websocket
1 jsonp
<script type="text/javascript">
//1jsonp
// 缺点:只能发送get请求,不支持post put delete,不安全
function jsonp({url,params,cb}){
return new Promise((resolve,reject)=>{
window[cb]=function(data){
resolve(data);
document.body.remove(script);
}
params={...params,cb}
let arrs=[];
for(let key in params){
arrs.push(`${key}=${params[key]}`)
}
let script=document.createElement('script');
script.src=`${url}?${arrs.join('&')}`;
document.body.appendChild(script);
})
}
jsonp({
url:'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',
params:{
wd:'b'
},
cb:'show'
})
.then(res=>{
console.log(res)
})
.catch(err=>{
console.log(err)
})
</script>
2 cors
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
//2cors
let xhr=new XMLHttpRequest;
document.cookie="name=afpx";
// 强制带好凭证再发送请求
xhr.withCredentials=true;
xhr.open('PUT','http://localhost:4000/getData',true);
xhr.setRequestHeader('name','afpx')
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status>=200 && xhr.status<300 || xhr.status==304){
console.log(xhr.response)
}
}
}
xhr.send();
</script>
</body>
</html>
server.js
let express=require('express');
let app=express();
app.use(express.static(__dirname));
app.listen(3000);
server2.js
let express=require('express');
let app=express();
let whiteList=['http://localhost:3000']
app.use(function(req,res,next){
let origin=req.headers.origin;
if(whiteList.includes(origin)){
// 设置哪个源可以访问
res.setHeader('Access-Control-Allow-Origin',origin)
// 设置加请求头
res.setHeader('Access-Control-Allow-Headers','name')
// 添加请求方法
res.setHeader('Access-Control-Allow-Methods','PUT')
// 预检的存活时间
res.setHeader('Access-Control-Max-Age',6000)
// 允许前端获取哪个头
res.setHeader('Access-Control-Expose-Headers','name')
if(req.method=='OPTIONS'){
res.end();//OPTIONS请求不做任何处理
}
}
next();
})
app.get('/getData',function(req,res){
console.log(req.headers);
res.end('hahaha')
})
app.put('/getData',function(req,res){
console.log(req.headers);
res.end('hahaha')
})
app.use(express.static(__dirname));
app.listen(4000);
3 postMessage
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<iframe
src="http://localhost:4000/index2.html"
id="iframe"
onload="load()">
</iframe>
<script type="text/javascript">
//3
function load(){
let frame=document.getElementById('iframe');
frame.contentWindow.postMessage('我爱你','http://localhost:4000')
window.onmessage=function(e){
console.log(e.data)
}
}
</script>
</body>
</html>
index2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
window.onmessage=function(e){
console.log(e.data)
e.source.postMessage('我不爱你',e.origin);
}
</script>
</body>
</html>
server.js
let express=require('express');
let app=express();
app.use(express.static(__dirname));
app.listen(3000);
server2.js
let express=require('express');
let app=express();
app.use(express.static(__dirname));
app.listen(4000);
4 window.name
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- index和index2是同域的,http://localhost:3000
index3是独立的,http://localhost:4000
index获取index3的数据
index先引用index3 index3把值放到window.name 把index引用的地址改到index2 -->
<iframe
src="http://localhost:4000/index3.html"
id="iframe"
onload="load()">
</iframe>
<script type="text/javascript">
let first=true;
function load(){
if(first){
let iframe=document.getElementById('iframe');
iframe.src="http://localhost:3000/index2.html"
first=false;
}else{
console.log(iframe.contentWindow.name)
}
}
</script>
</body>
</html>
index2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
</script>
</body>
</html>
index3.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script>
window.name="我不爱你"
</script>
</body>
</html>
server.js
let express=require('express');
let app=express();
app.use(express.static(__dirname));
app.listen(3000);
server2.js
let express=require('express');
let app=express();
app.use(express.static(__dirname));
app.listen(4000);
5 location.hash
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- 路径后面的hash值可以用来通信 -->
<!-- 目的:index想访问index3
index给index3传一个hash值,
index3收到hash值后
index3把hash值传递给index2
index2将结果放到index的hash值中 -->
<iframe
src="http://localhost:4000/index3.html#iloveyou"
id="iframe">
</iframe>
<script type="text/javascript">
window.onhashchange=function(){
console.log(location.hash)
}
</script>
</body>
</html>
index2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
window.parent.parent.location.hash=location.hash;
</script>
</body>
</html>
index3.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script>
console.log(window.location.hash)
let iframe=document.createElement('iframe');
iframe.src="http://localhost:3000/index2.html#idontloveyou"
document.body.appendChild(iframe);
</script>
</body>
</html>
6 document.domain
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
helloa
<!-- 限制:必须是一级域名和二级域名的关系,并且配置 -->
<!-- 一级域名 www.baidu.com -->
<!-- 二级域名 viode.baidu.com -->
<!-- index是通过http://localhost:3000/index.html -->
<iframe
src="http://localhost:3000/index2.html"
id="iframe"
onload="load()">
</iframe>
<script type="text/javascript">
document.domain="zf1.cn"
function load(){
var iframe=document.getElementById('iframe')
console.log(iframe.contentWindow.a);
}
</script>
</body>
</html>
index2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
hellob
<script type="text/javascript">
document.domain="zf1.cn"
var a=100;
</script>
</body>
</html>
7 websocket
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
// 高级api 不兼容 socket.io(一般使用它)
let socket=new WebSocket('ws://localhost:3000');
socket.onopen=function(){
socket.send('我爱你');
}
socket.onmessage=function(e){
console.log(e)
}
</script>
</body>
</html>
server.js
let express=require('express');
let app=express();
let WebSocket=require('ws');
let wss=new WebSocket.Server({port:3000});
wss.on('connection',function(ws){
ws.on('message',function(data){
console.log(data)
ws.send('我不爱你')
})
});
8 nginx
先下载nginx,然后配置
9 http-proxy
以后再学