面试之:前端跨域的方法

JSONP跨域
JSONP的实现原理:

(1).客户端动态创建<script>,借助script发送请求,并给服务器端传递一个callback函数
<script src=”http://localhost:2000?callback=show”>
(2).服务器端接收传来的callback中的函数,将要返回的数据作为参数放入到函数名中,并转换为字符串返回给客户端。客户端接收到返回的信息就会执行这个函数。JSONP原理

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>
location.hash+iframe(由于url传递长度有限,不推荐)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值