• web前端_跨域问题方法总结


    文章内容基于个人总结,如有问题欢迎评论。

    1.何为跨域

    关于网站的跨域问题,简单的说就是不同协议(如http|https)不同域名(如www.a.com|www.b.com|a.b.com)或者不同端口号(:3000|3001)之间的请求访问,都会产生同源限制导致请求失败。

    2.解决方案

    下面展示5种解决方案(包含代码及部分思路)

     1) jsonp 根据script标签请求不会产生同源限制的原理 (局限在于只能发送get请求,及请求长度有限制)

    客户端:

    <div id="jsonp"></div>
    
    <script type="text/javascript">
         function jsonpCallBack(data) {
            document.getElementById('jsonp').textContent = 'jsonp跨域callback-' + JSON.stringify(data);
        }
    </script>
    
    <script src="http://localhost:3000/api/jsonp?jsonp=jsonpCallBack"></script>
    View Code

    服务器端:

    router.all('/jsonp', function(req, res, next) {
        var callback = req.query.jsonp;
        var obj = {name: 'tom', hobby: [1,2,3]};
        res.send(callback ? callback + '(' + JSON.stringify(obj) + ')' : 'jsonp response');
    });
    View Code

    思路: 在客户端先定义好callback方法,将方法作为url参数传到服务器端,服务器端返回方法调用并回传参数让客户端方法处理。

     2) cors跨域 设置Access-Control-Allow-[Origin|Methods|Headers]等参数开启跨域许可

    客户端:

    <div id="cors"></div>
    <script type="text/javascript">
        fetch('http://localhost:3000/api/cors', { method: 'get', mode: 'cors', cache: 'default' })
            .then(res => res.json())
            .then(data => {
                document.getElementById('cors').textContent = 'cors跨域-' + data;
        });
    </script>
    View Code

    服务器端:

    router.all('/cors', function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");  // 最简设置
      res.json('cors response');
    });
    View Code

      3) iframe + window.name

    客户端:

    <div id="iframe"></div>
    <iframe src="http://localhost:3000" style="display: none" onload="iframeOnload()"></iframe>
    
    <script type="text/javascript">
        document.domain = 'localhost';
    
        function iframeOnload() {
            var iframe = document.getElementsByTagName('iframe')[0];
            var win = iframe.contentWindow;
            win.fetch('http://localhost:3000/api').then(res =>         
                res.json().then(data => {                
                    document.getElementById('iframe').textContent = 'iframe跨域-' + data;
            }));
        };
    </script>   
    View Code

    服务器端:

    router.all('/', function (req, res, next) {
        res.json('api response');
    });
    View Code

    思路: 比较重要的一步是iframe页和请求页需要设置相同的domain, 即代码中执行的document.domain = 'localhost'这一段。

     4) iframe + postMessage

    客户端:

    <div id="postMsg"></div>
    <iframe src="http://localhost:3000" style="display: none" onload="postOnload()"></iframe>
    
    <script type="text/javascript">
        document.domain = 'localhost';
    
        window.onmessage = function(e) {
            document.getElementById('postMsg').textContent = e.data;
            console.log('client window:' + e.data);
        }
    
        function postOnload() {
            var iframe = document.getElementsByTagName('iframe')[0];
            var win = iframe.contentWindow;
            win.postMessage('test', '*');
            // postMessage
            postMessage('postMsg response', '*');
        }
    </script>
    View Code

    思路: 这里win.postMessage是给iframe发送消息,直接的postMessage是给自己发送消息。如果在iframe页面想给本页面发消息,则需要用window.parent.postMessage发送消息。

     5) nginx反向代理

     这个方式的实现就是修改下nginx配置,如

    server {
        listen 3001;
        server_name localhost;
    
        location /api {
            proxy_pass http://127.0.0.1:3000/api;
        }
    }
    View Code

     通过这种设置就把本地3001端口的请求映射到3000端口去,然后就可以正常的发送之前同源限制的api接口了, 如客户端代码:

    <div id="nginx"></div>
    <script type="text/javascript">
        fetch('/api').then(res => res.json()).then(data => {
            nginx.textContent = 'nginx反向代理跨域-' + data;
        })
    </script>
    View Code

    3. 总结

    基本的几种方式就是这样,当然都是一些抛砖引玉的小实现思路,具体问题还是得具体分析的。然后,一些代码用到了像es6语法或者fetch api,有看不懂的。。还是补补课吧,毕竟还是比较通用流行的了。

  • 相关阅读:
    判断两个链表是否相交
    【转】TCP连接突然断开的处理方法
    【转】TCP/IP协议——ARP详解
    HTTP协议COOKIE和SESSION有什么区别
    【转】K-Means聚类算法原理及实现
    【转】机器学习实战之K-Means算法
    unity3d 调用Start 注意
    u3d 加载PNG做 UI图片
    Opengl的gl_NormalMatrix
    OpenGL 遮挡查询
  • 原文地址:https://www.cnblogs.com/easyToCode/p/4978735.html
Copyright © 2020-2023  润新知