html前端跨域处理

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/szc2000/article/details/51208050

html前端跨域处理

什么是跨域

浏览器出于安全性的考虑,受到javasript的同源策略的影响,不允许调用其他页面的对象.使得A页面无法调用非同源的BURL的iframe ajax应用.

什么是javasript的同源策略

简单的来说,URL符合以下三个条件之一

1.url的域名相同(或ip相同)

2.应用服务的端口号相同

3.相关的协议相同

什么样的非同源可以解决

由协议/端口造成的跨域问题前端无解,只有域名不同产生的跨域可以解决

跨域的解决方案

1.动态的创建<script>标签/jsonp跨域

思路:前端创建script标签,设置src,添加到head里,服务端返回一个js变量的jsonp,这个jsonp就是请求的返回的数据,回调完毕后,删除相应的script标签,并清理一些不必要的内存空间

前端

    <head></head>
    <script>
        /**
         *定义执行的回调函数 
         * @param result
         */
        var getdata=function(result){
             alert(result);
        }
        var eleScr=document.createElement('script');
        eleScr.src="http://127.0.0.1/demo2/kuayu/data.php?callback=getdata";  //url中指明需要回调的函数
        eleScr.type="text/javascript";
        document.getElementsByTagName('head')[0].appendChild(eleScr);  //创建一个动态的script脚本
        document.getElementsByTagName('head')[0].removeChild(eleScr);  //销毁这个script脚本
    </script>

后端 以php处理为例 url:http://127.0.0.1/demo2/kuayu/data.php?callback=getdata

$callback=$_GET['callback'];  //执行回调的js函数
echo $callback."('this is jsonp');";

注意:

  • jsonp不代表传送的值只为json,也可以是其他类型的,例如string
  • jsonp的原理和Ajax是不同的,在jquery中使用同一个一个模块,是因为jquery已经将jsonp封装到$.ajax中
  • Ajax通过服务器一些规则的修改也是可以进行跨域操作的

2.通过修改html文档中的域 (document.domain)

如果遇到主域相同,但是子域不同的情况,我们可以通过修改document.domain来进行跨域

下面举一个例子:a.test.com/demo3/a.html去请求 test.com/demo3/b.html

通过将两个页面的原始域为相同的

a.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    </body>
    <script>
        document.domain = 'test.com';
        var ifr = document.createElement('iframe');
        ifr.src = 'http://a.test.com/demo2/b.html';
        document.body.appendChild(ifr);
        ifr.onload = function(){
            var doc = ifr.contentDocument || ifr.contentWindow.document;
            alert(doc.getElementById('but').value);
        };
    </script>
    </html>

b.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <button id="but" value="this is b.html"></button>
    </body>
    <script>
        document.domain = 'test.com';
    </script>
    </html>

3.使用location.hash跨域

首先改变域名的hash不会导致页面刷新,可以通过动态创建一个iframe标签,修改父页面的hash,来实现跨域

下面展示一个例子

http://test.com/demo2/cs1.html去请求http://a.test.com/demo2/cs2.html的数据

由于chrome IE的安全限制,二个非同域的页面无法相互修改hash值,所以在这个需要用到一个跟cs1.html同域的代理页面

cs1.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    </body>
    <script>
            var ifr = document.createElement('iframe');
            ifr.style.display = 'none';
            ifr.src = 'http://a.test.com/demo2/cs2.html';
            document.body.appendChild(ifr);
            var data = location.hash ? location.hash.substring(1) : '';
            console.log('The data is from '+data);
    </script>
    </html>

cs2.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    </body>
    <script>
            try {
                parent.location.hash = 'b.html';
            } catch (e) {
                var ifrproxy = document.createElement('iframe');
                ifrproxy.style.display = 'none';
                ifrproxy.src = 'http://test.com/demo2/cs3.html#b.html';    // 注意该文件在"test.com"域下
                document.body.appendChild(ifrproxy);
            }
    </script>
    </html>

cs3.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    </body>
    <script>
        parent.parent.location.hash = self.location.hash.substring(1);
    </script>
    </html>

这个方法缺点十分明显

1.数据暴露在url中
2.数据传输的大小有限,本身url的长度就有限制

4.使用window.name进行跨域

window其中的name属性是一个浏览器窗口中的共享值,其中所有的页面都共享这个值.首先,将要传输的内容放在请求页面的window.name中,不同的浏览器的对其的内容长度限制不一样,chrome,可以达到2M. 利用iframe加载请求页面,加载完毕后更换iframe的资源路径,换为与当前页面同源的url(也可以是about:blank),就可以获取请求页面中的window.name了,这样既安全,又绕过浏览器的跨域限制.

下面举一个例子

http://test.com/demo2/a.html 去请求http://a.test.com/demo2/b.html

a.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    </body>
    <script>
        var iframe = document.createElement('iframe');
        iframe.src = 'http://a.test.com/demo2/b.html';
        iframe.οnlοad=function(){
            iframe.contentWindow.location = "about:blank";
            iframe.οnlοad=function(){
                var data = iframe.contentWindow.name;    // 读取数据
                alert(data);
            }
        }
        document.body.appendChild(iframe);
    </script>
    </html>

b.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    </body>
    <script>
        window.name = 'The data is from b';
    </script>
    </html>

5.使用HTML5 postMessage

h5的新标准增加了一个新的功能 跨文档消息传输Cross Document Messaging

现代主流浏览器都已经实现这个功能

例如 http://localhost/demo3/a.htmlhttp://127.0.0.1/demo3/b.html的相互通讯

a.html

    <iframe src="http://127.0.0.1/demo3/b.html" id="b"></iframe>
    <script>
        window.οnlοad=function(){
            var biframe=document.getElementById('b');
            biframe.contentWindow.postMessage("hello world","http://127.0.0.1");
        }
    </script>

b.html

    <script>
        window.addEventListener('message',function(event){
            if(event.origin == 'http://localhost')
            alert(event.data);  // a页面的hello world
        },false)
    </script>

**ps:**contentWindow.postMessage(); 中的参数,第一个是要传送的数据(string) ,第二个请求的域

展开阅读全文

没有更多推荐了,返回首页