9种跨域方式总结

1、jsonp
2、CORS
3、http proxy
4、nginx反向代理
5、postMessage
6、document.domain + iframe
7、window.name + iframe
8、location.hash + iframe
9、webSocket

1、jsonp

script标签的src属性没有跨域问题,可以利用这一特点实现跨域资源共享。

// localhost:5500
<script>
        function test1(data) {
            console.log(data)
        }
    </script>
    <script src="http://localhost:8001/list?callback=test1"></script>
//localhost:8001
//使用了express搭建web服务器
const express = require('express'),
app=express()
app.listen(8001,()=>{
    console.log('OK!')
})

app.get('/list',(req,res)=>{
     let {callback}=req.query
     let data={
         code:0,
         message:'this is send'
     }
     res.send(`${callback}(${JSON.stringify(data)})`)
})

缺点是只能使用get请求

2、CORS

需要后端实现。get、post等等都可以
后端用的express.js

//后端 http://127.0.0.1:8001
const express = require('express'),
app=express()
app.listen(8001,()=>{
    console.log('OK!')
})

app.use((req,res,next)=>{
    res.header('Access-Control-Allow-Origin','http://127.0.0.1:5500')
    res.header('Access-Control-Allow-Credentials',true)
    res.header('Access-Control-Allow-Headers','Content-Type,Content-Length,Authorization,Accept,')
    res.header('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS,HEAD')
    next()
})

app.get('/list',(req,res)=>{
     let data={
         code:0,
         message:'this is send'
     }
     res.send(data)
})
//前端 http://127.0.0.1:5500
//使用axios发送请求
  <script src="axios.js"></script> //引入axios
    <script>
        axios.get('http://127.0.0.1:8001/list').then(res=>{
            console.log(res)
        })
    </script>

3、http proxy

使用webpack的webpack-dev-server实现
在webpack.config.js配置文件中加入以下代码:

devServer:{
	proxy: {
	//所有以/api开头的请求都会被代理到http://localhost:3000
	  "/api": "http://localhost:3000"
	}
}

具体见webpack配置文档

4、nginx反向代理

在nginx的配置文件nginx.conf中做如下配置

server {

    listen       80;

    server_name  www.test.com;    //要访问的域名,我这里用的测试域名,如果有多个,用逗号分开

 

    charset utf8;

 

    location / {

        proxy_pass       http://proxy_test;              //这里proxy_test是上面的负载的名称,映射到代理服务器,可以是ip加端口,   或url 

        proxy_set_header Host      $host;

        proxy_set_header X-Real-IP $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

      }

   }

5、postMessage

//localhost:5500 a.html
<body>
 <iframe src="http://localhost:5501/b.html" id="testa" frameborder="0"></iframe>
 <script>
testa.onload=function(){ //id为testa的iframe加载完毕
    //向http://127.0.0.1:5501/b.html 发送消息
    testa.contentWindow.postMessage('this is test send','http://127.0.0.1:5501/b.html')
}
window.onmessage=function(ev){ //监听其它页面发送过来的消息
    console.log(ev.data) //输出发送来的消息
    
}
</script>
 </body>
 //localhost:5501 b.html
    <script>
        let name='this is b.html'
        window.onmessage=function(ev){ //监听其它页面发送来的消息
            console.log(ev.data) //输出其它页面发送来的消息
            //向http://127.0.0.1:5500/a.html发送消息
            ev.source.postMessage(name,'http://127.0.0.1:5500/a.html')
        }
    </script>

6、document.domain + iframe

只能实现同一个主域不同子域之间的操作
如 a.test.com和b.test.com就是同一个主域不同子域

//父页面 A a.test.com
<iframe src="http://b.test.com"></iframe>
<script>
  document.domain = 'test.com'
  var user = 'admin'
  //子页面B b.test.com
  <script>
    document.domain='test.com'
    alert(window.parent.user)
  </script>

7、window.name + iframe

// http://127.0.0.1:5500 a.html
    <iframe src="http://127.0.0.1:5501/b.html" id="testa" frameborder="0"></iframe>
    <script>
        let count=0
        testa.onload=function(){
        //判断count等于0 是为了防止onload事件反复触发
            if(count===0){ 
                //需要我们先把地址重新定向到同源中才可以
                testa.src='http://127.0.0.1:5500/proxy.html'
                count++
                return;
            }
            //如果不把testa的src指定到一个同源的页面中而直接输出
            //5501 b页面传过来的值的话,会出现跨域问题而无法输出
            //将testa的src指定到一个空白的同源页面,不会覆盖掉5501 b页面传过来的值
            console.log(testa.contentWindow.name)
        }
    </script>
// http:127.0.0.1:5501 b.html
window.name='this is b.htmlllll'
// http:127.0.0.1:5500 proxy.html
//proxy.html为空

8、location.hash + iframe

// a c页面同源 b非同源
// http://127.0.0.1:5500 a.html
    <iframe src="http://127.0.0.1:5501/b.html" id="testa" frameborder="0"></iframe>
    <script>
        let count=0
        testa.onload = function () {
            if(count===0){
                //向b.html传hash值
                testa.src = 'http://127.0.0.1:5501/b.html#msg=yaochuandezhi'
                count++
                return;
            }
            
        }
        //开放给同域c.html的回调方法
        function func(res) {
            console.log(res)
        }
   </script>
// http://127.0.0.1:5501 b.html
   <iframe src="http://127.0.0.1:5500/c.html" id="iframe" frameborder="0"></iframe>
    <script>
        let iframe= document.querySelector('#iframe')
        //监听a传来的hash值,再传给c.html
        window.onhashchange=function(){
            console.log(location.hash)
            iframe.src="http://127.0.0.1:5500/c.html"+location.hash
        }
    </script>
// http://127.0.0.1:5500 c.html
<script>
        //监听b传来的hash值
        window.onhashchange=function(){
            //在通过操作同域a的js回调,将结果传回
            window.parent.parent.func(location.hash)
        }
    </script>

9、webSocket

//客户端
    <script src="./socket.io.js"> </script>
    <script>
        let socket = io('http://127.0.0.1:5501')
        //连接成功
        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('lalalalallala')
   </script>
//服务端 用node和express搭建
//安装socket模块 监听socket连接:server是服务器创建的服务
socket.listen(server).on('connection',function(client){
    //接收消息
    client.on('message',function(msg){
        client.send(msg+'fasdlfasdfasf')
    })
    //断开处理
    client.on('disconnect',function(){
        console.log('client socket has closed')
    })
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值