解决跨域问题

解决跨域的十种方案

跨域原因:网络请求时,协议,IP地址,域名其中的一个于源目标地址有不同的时候出现跨域问题解决跨域的方法:

  注意:1.如果是协议和端口造成的跨域问题,前端无法处理;

     2.是否跨域,仅仅通过URL的首部来判断,不会通过域名对应的IP地址是否相同来判断;

     3.跨域并不是请求发不出去,而是请求发出去了,也正常返回结果了,但是结果被浏览器拦截了。


方案一

  • JSONP来解决跨域
    • 注意:支持GET请求,一定要浏览器支持才可以
    • JSONP是非同源策略,AJAX属于同源策略。 
利用script标签没有跨域的限制,网页可以从其他来源动态的获取JSON数据,从而实现跨域。

创建JSONP 的原理及步骤
①创建script
	let script =document.createElement("script");
②设置src属性
	script.src="url地址";
③把创建好的标签插入到body中
	document.body.appendChild(script)
④回调函数
	function callback(res){
//res就是调取jsonp之后的响应
}
注意:什么是JSONP的接口
	?后面以cb或者callback为第一个参数的就是jsonp接口

方案二

  • 利用H5的websocket协议,实现浏览器与服务器的即时通信,同时允许跨域通讯
    • 服务器代理
// socket.html
<script>
    let socket = new WebSocket('ws://localhost:3000');
    socket.onopen = function () {
      socket.send('我爱你');//向服务器发送数据
    }
    socket.onmessage = function (e) {
      console.log(e.data);//接收服务器返回的数据
    }
</script>
// server.js
let express = require('express');
let app = express();
let WebSocket = require('ws');//记得安装ws
let wss = new WebSocket.Server({port:3000});
wss.on('connection',function(ws) {
  ws.on('message', function (data) {
    console.log(data);
    ws.send('我不爱你')
  });
})

方案三

  • webpack proxy
    • 代理服务器
//服务器启动目录;
  devServer: {
    contentBase: './dist',
    hot: true,
    // host:'1ocalhost',
    port: 8586,
    // compress:true,

    //解决跨域
    proxy: {
      '/api': {
        target: 'http://localhost:8087',
        pathRewrite: { '^/api': '' },
        changeOrigin: true,
        secure: false, // 接受 运行在 https 上的服务
      }
    }
  },

方案四

  • CORS(Cross-Origin Resource Sharing)技术
    • 需要前后端同时支持
前端浏览器在IE9以上,后端在响应报头添加Access-Control-Allow-Origin标签,从而允许指定域的站点访问当前域上的资源。

res.setHeader("Access-Control-Allow-Origin","*");
不过CORS默认只支持GET/POST这两种http请求类型,如果要开启PUT/DELETE之类的方式,需要在服务端在添加一个"Access-Control-Allow-Methods"报头标签。

方案五

  • 利用H5的postMessage 方法和 onmessage 事件解决跨域问题

    • 可实现多窗口之间的数据传递
  • postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。


方案六

  • window.name
    • window.name 属性的独特之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

    • a、b页面同域,a页面嵌套c页面,onload事件第一次载入c页面url变为b页面并且获取contentWindow.name

// a.html(http://localhost:3000/b.html)
  <iframe src="http://localhost:4000/c.html" frameborder="0" onload="load()" id="iframe"></iframe>
  <script>
    let first = true
    // onload事件会触发2次,第1次加载跨域页,并留存数据于window.name
    function load() {
      if(first){
      // 第1次onload(跨域页)成功后,切换到同域代理页面
        let iframe = document.getElementById('iframe');
        iframe.src = 'http://localhost:3000/b.html';
        first = false;
      }else{
      // 第2次onload(同域b.html页)成功后,读取同域window.name中数据
        console.log(iframe.contentWindow.name);
      }
    }
  </script>
// c.html(http://localhost:4000/c.html)
  <script>
    window.name = '我不爱你'
  </script>

方案七

  • hash
    • a中嵌套c,c中嵌套b,a=>b=>c传递location.hash,a页面用window.onhashchange获取hash值
// a.html
  <iframe src="http://localhost:4000/c.html#iloveyou"></iframe>
  <script>
    window.onhashchange = function () { //检测hash的变化
      console.log(location.hash);
    }
  </script>
 // b.html
  <script>
    window.parent.parent.location.hash = location.hash
    //b.html将结果放到a.html的hash值中,b.html可通过parent.parent访问a.html页面
  </script>
 // c.html
 console.log(location.hash);
  let iframe = document.createElement('iframe');
  iframe.src = 'http://localhost:3000/b.html#idontloveyou';
  document.body.appendChild(iframe);

方案八

  • document.domain
    • 必须是一级域名和二级域名的关系
// a.html
<body>
 helloa
  <iframe src="http://b.zf1.cn:3000/b.html" frameborder="0" onload="load()" id="frame"></iframe>
  <script>
    document.domain = 'zf1.cn'
    function load() {
      console.log(frame.contentWindow.a);
    }
  </script>
</body>
// b.html
<body>
   hellob
   <script>
     document.domain = 'zf1.cn'
     var a = 100;
   </script>
</body>

方案九

  • nginx
    • 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。
使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。

实现思路:通过 nginx 配置一个代理服务器(域名与 domain1 相同,端口不同)做跳板机,反向代理访问 domain2 接口,并且可以顺便修改 cookie 中 domain 信息,方便当前域 cookie 写入,实现跨域登录。

先下载nginx,然后将 nginx 目录下的 nginx.conf 修改如下:
// proxy服务器
server {
    listen       80;
    server_name  www.domain1.com;
    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
        index  index.html index.htm;

        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}

方案十

  • webpack proxy
//服务器启动目录;
  devServer: {
    contentBase: './dist',
    hot: true,
    // host:'1ocalhost',
    port: 8586,
    // compress:true,

    //解决跨域
    proxy: {
      '/api': {
        target: 'http://localhost:8087',
        pathRewrite: { '^/api': '' },
        changeOrigin: true,
        secure: false, // 接受 运行在 https 上的服务
      }
    }
  },

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值