JSONP跨域
JSONP的实现原理:
(1).客户端动态创建<script>,借助script发送请求,并给服务器端传递一个callback函数
<script src=”http://localhost:2000?callback=show”>
(2).服务器端接收传来的callback中的函数,将要返回的数据作为参数放入到函数名中,并转换为字符串返回给客户端。客户端接收到返回的信息就会执行这个函数。
JSONP实现跨域
客户端
$.ajax({
url:"http://127.0.0.1:8001/list",
method:"get",
dataType:"JSONP",
success:res=>{
console.log(res)
}
})
服务器端
let express=require("express")
let app=express() //创建服务器服务
app.listen(8001,_=>{ //_等用于()
console.log("ok")
})
app.get('/list',(req,res)=>{
let{
callback=Function.prototype //赋一个默认值,空函数
}=req.query //接收客户端传递过来的callback参数
let data={ //返回的数据
code:0,
message:"返回的数据"
}
res.send(`${callback}(${JSON.stringify(data)})`) //返回的内容
})
- JSONP只能处理get请求
- 如果服务器返回的内容有木马,客户端执行后就会产生安全问题
CORS跨域资源共享
客户端
发送ajax/fetch请求
axios.get("http://127.0.01:3001/user/list").then(
res => {
console.log(res)
}
)
服务器端
设置相关的头信息(需要处理options试探性请求)
app.use((res, req, next) => {
res.header("Access-Control-Allow-Origin", "http://localhost:8000");//允许接收请求的域名,必须
res.header("Access-Control-Allow-Credentials", true);//是否允许发送cookie,可选
//允许的请求头
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length,Authorization,Accept,X-Requested-With")
//允许的请求方式
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,HEAD,OPTIONS")
//所有的cors跨域请求都会预先发送一个options请求,options是试探性请求,服务器接收到options请求,返回成功信息,告诉客户端能建立请求
if (req.methods === 'OPTIONS') {
res.send("OK")
return
}
next()
})
http proxy(http代理)
配合webpack ,webpack-dev-server 实现
发送请求
axios.get("/user/list").then(
res => {
console.log(res)
}
)
webpack.config.js中设置代理
devServer:{
proxy:{
'/':{
target:"http://127.0.0.1:3001",
changeOrigin:true
}
}
}
nginx反向代理
不需要前端处理
postMessage
window.postMessage() 方法可以安全地实现跨源通信。一个窗口可以获得对另一个窗口的引用,然后在窗口上调用targetWindow.postMessage() 方法分发一个 MessageEvent 消息。接收消息的窗口可以根据需要自由处理此事件。
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
message
将要发送到其他 window的数据。
targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。
transfer
是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
实现postMessage跨域
客户端A,端口号为1001
<iframe id="iframe" src="http://127.0.0.1:1002/B.html" frameborder="0" style="display: none;"></iframe>
<script>
//iframe.contentWindow获取B.html的内容
ifram.onload=function(){
iframe.contentWindow.postMessage("发送的数据","http://127.0.0.1:1002/")
}
//监听B传递过来的信息
window.onmessage=function(ev){
console.log(ev.data)//"发送的数据修改后的数据"
}
</script>
服务器端B,端口号为1002
//window.onmessage监听A传递过来的信息
window.onmessage=function(ev){
// ev.source代表A.html
//接收到信息后修改返回给A
ev.source.postMessage(ev.data+"修改后的数据",ev.origin)
}
WebSocket协议跨域
WebSocket是客户端与服务器段实时通信的协议
客户端
<script src="./socket.io.js"></script>
<script>
let socket = io("http://127.0.0.1:3001"); //服务器接口
//连接成功处理
socket.on("connect", function () {
//监听服务端消息
socket.on("message",function(msg){
console.log("data from server:"+msg)
});
//监听服务器端关闭
socket.on('disconnect',function(){
console.log("server socket has closed")
})
});
//发送消息给服务器端
socket.send("发送消息给服务器端")
</script>
服务器端
//监听socket连接,server是服务器创建的服务
socket.listen(server).on('connection',function(client){
//接受信息
client.on('message',function(msg){
//msg客户端传递过来的信息
//...
client.send(msg+'@@')
})
//断开处理
client.on('disconnect',function(){
console.log("client socket has closed")
})
})
document.domain+iframe
只能实现同一主域,不同子域之间的操作
父页面A:http://www.qq.com/A.html
<iframe src="http://sports.qq.com/B.html"></iframe>
<script>
document.domain="qq.com";
var test="hello"
</script>
子页面B :http://sports.qq.com/B.html
document.domain="qq.com";
alert(window.parent.test);//访问到父页面的变量
window.name +iframe
页面A httt://127.0.0.1:1001/A.html
<iframe src="http://127.0.0.1:1002/B.html" ></iframe>
<script>
let count=0
iframe.onload=function(){
if(count ===0){
//先将地址指向与当前页面同源的页面中才可以
iframe.src="http://127.0.0.1:1001/proxy.html"
count++
return
}
console.log(window.contentWindow.name) //访问源B.html的数据
}
</script>
页面proxy httt://127.0.0.1:1001/proxy.html 内容可为空
页面B httt://127.0.0.1:1002/B.html
<script>
window.name="要传递给前端的数据"
</script>