zoukankan      html  css  js  c++  java
  • jquery跨域解决方案JSONP

    1.在互联网中我们的计算机是通过IP来定位的,但是IP比较难记忆,因此通过domain name(域名)来取代IP

    2.什么是跨域?

    (1)默认浏览器为了安全问题,禁止了xmlhttprequest跨域访问

    (2)<script><iframe><img>等凡是有src属性的标签,默认都是可以访问跨域资源的。

    JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象在A域名中不能想访问B域名中的资源,就是跨域。a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。

    子域名不相同都算是跨域

    3.jquery采用jsonp的方式来解决跨域问题

    JSONP : JSON with Padding
    1.script标签
    2.用script标签加载资源是没有跨域问题的

    为什么用script标签可以实现没有跨域呢?

    就是因为script标签中的src属性,这个属性有两个作用,第一个可以将指定的资源下载下来,第二个就是不存在跨域问题。

    如果指定了script或jsonp类型,那么从服务器接收到数据时,实际是用了<script>标签(get 请求)而不是XMLHttpRequest对象。

     在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

     栗子1:

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>无标题文档</title>
    <script>
    function fn(data) {
        alert(data);
    }
    </script>
    <script src="2.txt"></script>
    <script>
    //alert(a);
    </script>
    </head>
    
    <body>
    
    </body>
    </html>

    2.txt文件里面的内容是:

    fn([1,2,3]);

    在资源加载进来之前定义好一个函数function fn(data){alert(data)};,这个函数接收一个参数(数据),函数里面利用这个参数做一些事情
    然后需要的时候通过script标签加载对应远程文件资源当远程的文件资源被加载进来的时候,文件里面有fn()函数,这样文件里面的函数就会去执行我们前面定义好的函数,并且把数据当作这个函数的参数传入进去

    栗子2:

    我们希望当点击按钮的时候,再去加载远程资源,让他执行。这个原理就是,动态创建script标签。

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>无标题文档</title>
    <script>
    function fn(data) {
        alert(data);
    }
    </script>
    <!--<script src="2.txt"></script>-->
    <script>
    window.onload = function() {
        
        var oBtn = document.getElementById('btn');
        
        oBtn.onclick = function() {
            
            //当按钮点击的时候再去加载远程资源,让他执行
            
            var oScript = document.createElement('script');
            oScript.src = '2.txt';
            document.body.appendChild(oScript);
            
        }
        
    }
    </script>
    </head>
    
    <body>
    
    </body>
    </html>

     栗子3:

    把wampserver服务器开启,把getData.php和这个jsonp跨域.html都放在miaov文件夹下。D:\wamp\www\miaov

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>jsonp跨域</title>
        <script>
        function fn(data){
            var oUl1=document.getElementById("ul1");
            var html='';
            for(var i=0;i<data.length;i++){
                html+='<li>'+data[i]+'</li>';
            }
            oUl1.innerHTML=html;    
        }
        </script>
        <script>
            window.onload=function(){
                var oBtn1=document.getElementById("btn1");
                oBtn1.onclick=function(){
                    var oScript=document.createElement("script");
                    oScript.src='getData.php';
                    document.body.appendChild(oScript);
                }
            }
        </script>
    </head>
    <body>
        <input type="button" id="btn1" value="按钮">
        <ul id="ul1"></ul>
    </body>
    </html>

    getData.php

    <?php
    
    $arr1 = array('11111','222222','333333','4444444','5555');
    
    echo 'fn('.json_encode($arr1).');';

     点击加载按钮后页面会这样:

     但是,如果不只一个按钮,有多个按钮,不可能还让后端也跟着改变,增加

    <?php
    $t=isset($_GET['t'])?$_GET['t']:'num';//默认是数字
    
    $arr1 = array('11111','222222','333333','4444444','5555');
    $arr2 = array('aaaaaaaaaaaa','bbbbbbbb','cccccccccccc','ddddddddd','eeeeeeeeeeee');
    
    //判断访问的参数,如果是num就输出$arr1,否则$arr2
    if($t=='num'){
        $data=json_encode($arr1);
    }else{
        $data=json_encode($arr2);
    }
    echo 'fn('.$data.');';

    这样做是不可取的。

     后端可以把接口做好,无论前端做了多少个按钮,只要把参数添加上去就可以访问的到,这样就可以实现动态的变化

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>jsonp跨域</title>
        <script>
        function fn1(data){
            var oUl1=document.getElementById("ul1");
            var html='';
            for(var i=0;i<data.length;i++){
                html+='<li>'+data[i]+'</li>';
            }
            oUl1.innerHTML=html;    
        }
    
        function fn2(data){
            var oUl2=document.getElementById("ul2");
            var html='';
            for(var i=0;i<data.length;i++){
                html+='<li>'+data[i]+'</li>';
            }
            oUl2.innerHTML=html;    
        }
    
        function fn3(data){
            var oUl3=document.getElementById("ul3");
            var html='';
            for(var i=0;i<data.length;i++){
                html+='<li>'+data[i]+'</li>';
            }
            oUl3.innerHTML=html;    
        }
        </script>
        <script>
            window.onload=function(){
                var oBtn1=document.getElementById("btn1");
                oBtn1.onclick=function(){
                    var oScript=document.createElement("script");
                    oScript.src='getData.php?callback=fn1';
                    document.body.appendChild(oScript);
                }
    
                var oBtn2=document.getElementById("btn2");
                oBtn2.onclick=function(){
                    var oScript=document.createElement("script");
                    oScript.src='getData.php?t=str&callback=fn2';
                    document.body.appendChild(oScript);
                }
    
                var oBtn3=document.getElementById("btn3");
                oBtn3.onclick=function(){
                    var oScript=document.createElement("script");
                    oScript.src='getData.php?callback=fn3';
                    document.body.appendChild(oScript);
                }
            }
        </script>
    </head>
    <body>
        <input type="button" id="btn1" value="加载数字">
        <ul id="ul1"></ul>
        <input type="button" id="btn2" value="加载字母">
        <ul id="ul2"></ul>
        <input type="button" id="btn3" value="加载数字">
        <ul id="ul3"></ul>
    </body>
    </html>

    getData.php

    <?php
    $t=isset($_GET['t'])?$_GET['t']:'num';//默认是数字
    $callback=isset($_GET['callback'])?$_GET['callback']:'fn1';//默认是fn1
    
    $arr1 = array('11111','222222','333333','4444444','5555');
    $arr2 = array('aaaaaaaaaaaa','bbbbbbbb','cccccccccccc','ddddddddd','eeeeeeeeeeee');
    
    //判断访问的参数,如果是num就输出$arr1,否则$arr2
    if($t=='num'){
        $data=json_encode($arr1);
    }else{
        $data=json_encode($arr2);
    }
    echo $callback.'('.$data.');';

    此时callback是函数

     实现的效果;

    栗子:

    同源策略是浏览器的安全基石,但互联网业务往往需要实现跨域通信,以下哪一种方案可以实现跨域?(D

      A.CSP

      B.AJAX

      C.Oauth

      D.CORS

    解释:

    同源策略(Same Origin Policy,SOP)是指浏览器请求的资源必须是同域名、同协议、同端口。不同源的客户端脚本(js,actionscript)在没有明确的授权的情况下不能读取对方的资源。
    跨源资源(CrossOrigin Resources Sharing,CORS )是一种允许多种资源在一个web页面请求域之外的另一个域的资源的协议,是为了让AJAX能够跨域而生的
    内容安全策略(Content Security Policy,CSP)是一种白名单机制,限制网站中是否可以包含某来源的内容。
    Oauth是一个关于授权的开放网络标准,相当于在客户端与服务器之间添加了一个授权层
     

    比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://example.com/data.php,那么a.html中的代码就可以这样:

    通过http://example.com/data.php?callback=dosomething得到的js文件,就是我们之前定义的dosomething函数,并且它的参数就是我们需要的json数据,这样我们就跨域获得了我们需要的数据。

    这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

    http://example.com/data.php这个文件是这样的

    最终输出的结果是:

    知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

    原理是一样的,只不过我们不需要手动的插入script标签以及定义回调函数。jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

    本文主要根据http://www.cnblogs.com/2050/p/3191744.html

  • 相关阅读:
    twitter分享问题(三)——Required oauth_verifier parameter not provided
    旋转数组的最小数字
    关系型数据库基础之:简单的数据查询
    twitter分享问题(一)——MISSING_ARG_APIKEY
    extern "C"的理解
    从一个链接错误探究GCC的链接库顺序
    GAE 博客——B3log Solo 0.4.0 正式版发布了!
    不使用资源文件动态创建对话框的做法
    GAE 博客——B3log Solo 0.4.0 正式版发布了!
    CodeBlocks启动多个进程实例的做法
  • 原文地址:https://www.cnblogs.com/GumpYan/p/5692119.html
Copyright © 2011-2022 走看看