zoukankan      html  css  js  c++  java
  • JavaScript跨域解决方式

    平时工作中经常被JavaScript跨域问题所困扰,其实有很多种解决方式,下面给大家介绍常用的几种:

    1.jsonp解决跨域问题

    客户端代码:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>jsonp-跨域</title>
    <script type="text/javascript" src="resources/js/jquery-1.8.3.min.js"></script>
    <script type="text/javascript">
        function callbackFn(data){
            data = typeof data != 'string' ? JSON.stringify(data) : data;
            console.log('callback:'+data);
        }
        function jsonpFn(){
            $.ajax({
                type:"get",
                dataType:"jsonp",
                url:"http://localhost:9393/ccy_server/server.jsp",
                jsonpCallback:"callbackFn",
                success:function(data){
                    data = typeof data != 'string' ? JSON.stringify(data) : data;
                    console.log('success.data:'+data);
                }
            });
        }
        function ajaxFn(){
            var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
            var url = "http://localhost:9393/ccy_server/server.jsp";
            xmlhttp.onreadystatechange = function(){
                if(xmlhttp.readyState==4){
                    if(xmlhttp.status==200){
                        callbackFn(xmlhttp.responseText);
                    }
                }
            }
            xmlhttp.open('GET',url,true);
            xmlhttp.send(null);
        }
        ajaxFn();
        //jsonpFn();
    </script>
    </head>
    <body>
    
    </body>
    </html>

    服务端代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%
        String result = "{"name":"ccy","age":18,"info":{"address":"wuhan","interest":"playCards"}}";
        out.println("callbackFn("+result+")");
    %>

    相信大家对此种方式并不陌生,需要引用jquery库文件,并且要与服务端进行协调处理。

    我先写了个简单的ajax调用非同源的异步请求直接报错

    执行jsonpFn方法


    成功获取服务端信息!

    2.window.name解决跨域问题

    在客户端浏览器中每个页面都有一个独立的窗口对象window,默认情况下window.name为空,在窗口的生命周期中,载入的所有页面共享一个window.name并且每个页面都有对此读写的权限,window.name会一直存在当前窗口,但存储的字符串不超过2M。

    http://localhost:8383/ccy_client/window_name.html代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>window.name-跨域</title>
    <script type="text/javascript">
        window.name = "我是 window.name 字符串";
        setTimeout(function(){
            window.location = "http://localhost:9393/ccy_server/window_name.html";
        },2000);
    </script>
    </head>
    <body>
    
    </body>
    </html>


    http://localhost:9393/ccy_server/window_name.html代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>window.name-跨域</title>
    <script type="text/javascript">
        var str = window.name;
        console.log('ccy_server.window_name:'+str);
    </script>
    </head>
    <body>
    
    </body>
    </html>

    chrome打印信息

    上面是以window.location跳转的方式获取window.name字符串信息,平时开发中经常需要异步获取,请继续往下看:

    http://localhost:8383/ccy_client/window_name_iframe.html代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>window.name-跨域</title>
    </head>
    <body>
    <script type="text/javascript">
        var boo = false;
        var iframe = document.createElement('iframe');
        var loadData = function() {
            if (boo) {
                var data = iframe.contentWindow.name;    //获取window.name
                console.log(data); 
                //销毁数据   
                iframe.contentWindow.document.write('');
                iframe.contentWindow.close();
                document.body.removeChild(iframe);
            } else {
                boo = true;
                iframe.contentWindow.location = "";    // 设置的代理文件,iframe重新载入
            }  
        };
        iframe.src = 'http://localhost:9393/ccy_server/window_name_iframe.html';
        if (iframe.attachEvent) {
            iframe.attachEvent('onload', loadData);
        } else {
            iframe.onload  = loadData;
        }
        document.body.appendChild(iframe);
    </script>
    
    </body>
    </html>

    http://localhost:9393/ccy_server/window_name_iframe.html代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>window.name-跨域</title>
    <script type="text/javascript">
        window.name = '我是 http://localhost:9393/ccy_server/window_name_iframe.html';
    </script>
    </head>
    <body>
    
    </body>
    </html>

    chrome打印信息

    成功获取非同源地址的数据信息,主要是通过iframe的src属性,类似含有src属性的标签都可以成功处理跨域问题(img,script)

     3.postMessage解决跨域问题

    h5新特性,window.postMessage(msg,targetOrigin);

    msg:传入的字符串信息

    targetOrigin:目标源(协议主机端口有效)

    同样借助iframe进行跨域操作

    http://localhost:8383/ccy_client/postMessage.html代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>postMessage-跨域</title>
    </head>
    <body>
    <iframe id="ifr" src="http://localhost:9393/ccy_server/postMessage.html" style="display: none;"></iframe>
    <br>
    <input id="txt" type="text" style="600px;height:70px;"/>
    <br>
    <input id="btn" type="button" value="获取9393数据" onclick="getData();" style="180px;height:60px;"/>
    <script type="text/javascript">
        var data;
        function handleMsg(e){
            e = e || event;
            data = e.data;
            console.log('8383:'+e.data);
        }
        if(window.addEventListener){
            window.addEventListener('message', handleMsg);
        }else{
            window.attachEvent('onmessage', handleMsg);
        }
        function getData(){
            document.getElementById('txt').value=data;
            var msg = 'http://localhost:8383/ccy_client/postMessage.html';
            window.frames[0].postMessage(msg, 'http://localhost:9393');
        }
    </script>
    
    </body>
    </html>

    http://localhost:9393/ccy_server/postMessage.html代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>postMessage-跨域</title>
    </head>
    <body>
    <script type="text/javascript">
        function handleMsg(e){
            e = e || event;
            console.log('9393:'+e.data);
        }
        if(window.addEventListener){
            window.addEventListener('message', handleMsg);
        }else{
            window.attachEvent('onmessage', handleMsg);
        }
        window.onload = function(){
            var msg = '我是 http://localhost:9393/ccy_server/postMessage.html';
            window.parent.postMessage(msg, 'http://localhost:8383');
        }
    </script>
    
    </body>
    </html>

    chrome打印信息

    点击“获取9393数据”

    成功获取非同源数据,将非同源地址嵌入获取数据页面窗口。

    4.Java解决跨域问题

    通过客户端页面的ajax异步请求同源页面,再通过java的HttpURLConnect或者HttpClient进行转换即可,此处就不再赘述。

    还有一种就是设置服务端的Header,我们果果乐园新版的api就是这么处理的。

    5.参考资料

    https://www.sojson.com/blog/121.html

    https://www.jianshu.com/p/43ff69d076e3

    JavaScript权威指南

    欢迎纠错~~~

  • 相关阅读:
    Sass中连体符(&)的运用
    3211:花神游历各国
    ACM-ICPC 2017 Asia Urumqi(第八场)
    ACM训练联盟周赛(第三场)
    ACM训练联盟周赛(第一场)
    Nordic Collegiate Programming Contest 2015​(第七场)
    计算几何知识点简记
    The 2018 ACM-ICPC China JiangSu Provincial Programming Contest(第六场)
    2018 Multi-University Training Contest 1
    German Collegiate Programming Contest 2018​
  • 原文地址:https://www.cnblogs.com/ccylovehs/p/9357770.html
Copyright © 2011-2022 走看看