340 跨域:jsonp,jquery对于jsonp的封装,跨域资源共享(CORS)

【演示跨域问题.html】

jsonp

JSONP:JSON with Padding,可用于解决主流浏览器的跨域数据访问的问题。

原理:服务端返回一个预先定义好的javascript函数的调用,并且将服务器的数据以该函数参数的形式传递过来,这个方法需要前后端配合。

script 标签是不受同源策略的限制的,它可以载入任意地方的 JavaScript 文件,而并不要求同源。

类似的还有imglink标签。

<!--不受同源策略的标签-->
<script src="http://www.api.com/1.js"></script>
<img src="http://www.api.com/1.jpg" alt="">
<link rel="stylesheet" href="http://www.api.com/1.css">

jsonp演化过程

了解jsonp原理,同时jquery已经帮我们封装好了,我们使用起来非常的方便。

$.ajax({
    dataType:'jsonp',
})
dataType:jsonp 即可解决跨域;

jsonp的原理:
    在跨域的时候,发送ajax请求会受到浏览器的限制。
    在跨域的时候,通过XMLHttpRequest请求服务器会受到浏览器的限制, 在跨域的情况XMLHttpRequest无法成功请求服务器的,就算设置dataType:jsonp 也不行。

    其实在跨域情况下,$.ajax方法内部并没有使用XMLHttpRequest对象请求,而是使用其他方式来实现的。
    jsonp 和 XMLHttpRequest对象无关!!

    在跨域的情况下,$.ajax内部是如何请求服务器?

    jsonp本质是使用script的src属性跨域请求的服务器!;

    jsonp请求服务器的步骤:
        1-前端需要先定好一个方法,利用script将 把方法名传递给后台
        2-后台会获取方法名,然后在方法名后面拼接括号,在向括号中填充json数据
        3-后台会返回 填充好数据的方法调用,say({"name":"zs", "age":18});
        4-前端接受到返回的方法调用,会立即当做js执行,即可获取后台填充参数,进行使用

    注意点:
        1-jsonp只能发送get请求,jsonp具有get方式优点和缺点
        2-jsonp需要前端后配合才能完成
  •    前端:
       function say(obj) { }
       <script src="01.php?callback=say"></script>
    
       后台:
       echo $_GET['callback'].'('{"name":"zs"}')'  // say({"name":"zs"});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <!-- 
        jsonp本质是使用script的src属性跨域请求的服务器!;

        if (dataType=='json') {
        } else {
            //XMLHttpRequest 
        }

        在跨域的情况下,$.ajax内部是如何请求服务器?
        jsonp请求服务器的步骤:
        1-前端需要先定好一个方法,利用script将 把方法名传递给后台
        2-后台会获取方法名,然后在方法名后面拼接括号,在向括号中填充json数据
        3-后台会返回 填充好数据的方法调用  say({"name":"zs", "age":18});
        4-前端接受到返回的方法调用,会立即当做js执行, 即可获取后台填充参数,进行使用
     -->

     <!-- 跨域,能请求图片的 -->
     <!-- <img src="https://www.jisuapi.com/static/images/iconv2/aqi.png" alt=""> -->
     <!-- 跨域能请求js文件 -->
     <!-- <script src="http://www.test.com/11/test/test.js"></script> -->
     <!-- 标签src、href 都具备跨域请求资源的能力 -->
     <!-- src能跨域请求php程序 -->
     <!-- <script src="http://www.test.com/11/test/test.php"></script> -->
     <!-- script src 能向后台传递数据 -->
     <!-- <script src="http://www.test.com/11/test/test.php?name=zs"></script> -->

     <script>
         //前端有渲染数据方法,缺数据 
         function say(obj) {
             alert('你好' + obj.name);
         }

         var obj = {
             name: 'zs'
         }
     </script>
    <!-- 利用script标签将方法名传递给后台 -->
     <script src="http://www.test.com/11/test/test1.php?callback=say"></script>

</body>
</html>
<?php 
    // jsonp   json with padding   用json数据进行填充
    // 后台就是仓库,有的就是数据
    $info = [
        "name" => "xiaoming",
        "age" => 16
    ];

    $info = json_encode($info); // {"name":"xm", "age": 16}

    // 'say' . '('. '{"name":"xm", "age": 16}'. ')';

    echo $_GET['callback'].'('.$info.')';  // say({"name":"xm", "age": 16});

    // echo say({"name":"zs", "age": 18});

    //     $s1 = 'aaa';
    //     $s2 = 'bbb';
    //     $s3 = 'ccc';
    //    $s4= $s1 . $s2. $s3; // 'aaabbbccc'

    //echo say({"name":"xm", "age": 16});  json with padding
?>

jquery对于jsonp的封装

//使用起来相当的简单,跟普通的get请求没有任何的区别,只需要把dataType固定成jsonp即可。
$.ajax({
  type:"get",
  url:"http://www.api.com/testjs.php",
  dataType:"jsonp",
  data:{
    uname:"hucc",
    upass:"123456"
  },
  success:function (info) {
    console.log(info);
  }
});

案例:查询天气.html

http://lbsyun.baidu.com/index.php?title=car/api/weather

天气查询api地址

秘钥:zVo5SStav7IUiVON0kuCogecm87lonOj

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="../table.css">
    <style>
        img {
            width: 60px;
            height: 50px;
        }
    </style>
</head>

<body>
    <button>获取添加</button>
    <table></table>

    <!-- date: "周五 03月15日 (实时:19℃)"
    dayPictureUrl: "http://api.map.baidu.com/images/weather/day/duoyun.png"
    nightPictureUrl: "http://api.map.baidu.com/images/weather/night/duoyun.png"
    temperature: "19 ~ 7℃"
    weather: "多云"
    wind: "西北风3-4级"
    __proto__: Object -->
    <script type="text/html" id="tmp">
        {{ each list v i }}
        <tr>
            <td>{{ v.date }}</td>
            <td>{{ v.temperature }}</td>
            <td>{{ v.weather }}</td>
            <td>{{ v.wind }}</td>
            <td><img src="{{ v.dayPictureUrl }}" alt=""></td>
            <td><img src="{{ v.nightPictureUrl }}" alt=""></td>
        </tr>
        {{ /each }}
    </script>

    <script src="../jquery-1.12.4.min.js"></script>
    <script src="../template-web.js"></script>
    <script>
        //1-点击按钮,请求百度的天气预报接口,获取天气数据
        // http://api.map.baidu.com/telematics/v3/weather?location=北京&output=json&ak=E4805d16520de693a3fe707cdc962045
        //解决跨域使用jsonp
        $('button').click(function() {
            $.ajax({
                type: 'get',
                url: 'http://api.map.baidu.com/telematics/v3/weather',
                data: {
                    ak: 'zVo5SStav7IUiVON0kuCogecm87lonOj',
                    location: '上海',
                    output: 'json'
                },
                dataType: 'jsonp', //解决跨域 成功
                success: function(info) {
                    console.log(info.results[0].weather_data);
                    info = info.results[0].weather_data; //数组 
                    var obj = {
                        list: info
                    };
                    $('table').html(template('tmp', obj)); //绑定数据和模版
                }
            })
        });

        $.ajax({
            dataType: 'jsonp',
        })
    </script>
</body>

</html>

案例:省市区三级联动.html

api地址 : https://www.jisuapi.com/api/weather/

appkey: 3fa977031a30ffe1


图灵机器人:http://www.tuling123.com/


跨域资源共享(CORS)

使用jsonp跨域的缺点:
(1)麻烦,需要前后端人员相互配合,双方都要掌握jsonp;
(2)jsonp不能发送大量的数据给后台。

cors的使用

新版本的XMLHttpRequest对象,可以向不同域名的服务器发出HTTP请求。这叫做"跨域资源共享"(Cross-origin resource sharing,简称CORS)。

跨域资源共享(CORS)的前提

  • 浏览器支持这个功能
  • 服务器必须允许这种跨域。

服务器允许跨域的代码:

//允许所有的域名访问这个接口
header("Access-Control-Allow-Origin:*");
//允许www.study.com这个域名访问这个接口
header("Access-Control-Allow-Origin:http://www.study.com");

CORS的具体流程(了解)

  1. 浏览器会根据同源策略 查看是否是跨域请求,如果同源,直接发送ajax请求。
  2. 如果非同源,说明是跨域请求,浏览器会自动发送一条请求(预检请求 ),并不会携带数据,服务器接受到请求之后,会返回请求头信息,浏览器查看返回的响应头信息中是否设置了header('Access-Control-Allow-Origin:请求源域名或者*');
  3. 如果没有设置,说明服务器不允许使用cors跨域,那么浏览器不会发送真正的ajax请求。
  4. 如果返回的响应头中设置了header('Access-Control-Allow-Origin:请求源域名或者*');,浏览器会跟请求头中的Origin: http://www.study.com进行对比,如果满足要求,则发送真正的ajax请求,否则不发送。
  5. 结论:跨域行为是浏览器行为,是浏览器阻止了ajax行为,服务器与服务器之间是不存在跨域的问题的。

案例:图灵机器人

<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ajax</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #F7F7F7;
        }

        h3 {
            text-align: center;
        }

        .chatbox {
            width: 500px;
            height: 500px;
            margin: 0 auto;
            border: 1px solid #CCC;
            background-color: #FFF;
            border-radius: 5px;
        }

        .messages {
            height: 350px;
            padding: 20px 40px;
            box-sizing: border-box;
            border-bottom: 1px solid #CCC;
            overflow: scroll;
        }

        .messages h5 {
            font-size: 20px;
            margin: 10px 0;
        }

        .messages p {
            font-size: 18px;
            margin: 0;
        }

        .self {
            text-align: left;
        }

        .other {
            text-align: right;
        }

        .form {
            height: 150px;
        }

        .form .input {
            height: 110px;
            padding: 10px;
            box-sizing: border-box;
        }

        .form .btn {
            height: 40px;
            box-sizing: border-box;
            border-top: 1px solid #CCC;
        }

        .form textarea {
            display: block;
            width: 100%;
            height: 100%;
            box-sizing: border-box;
            border: none;
            resize: none;
            outline: none;
            font-size: 20px;
        }

        .form input {
            display: block;
            width: 100px;
            height: 30px;
            margin-top: 5px;
            margin-right: 20px;
            float: right;
        }

        iframe {
            position: absolute;
            left: 10px;
            top: 10px;
            /* border: 1px solid green; */
            width: 320px;
            height: 600px;
            box-shadow:  0 0  10px 0 #333;
        }
    </style>
</head>
<body>
    <h3>简单的Ajax实例</h3>
    <div class="chatbox">
        <!-- 聊天内容 -->
        <div class="messages">
        </div>
        <!-- 表单 -->
        <div class="form">
            <!-- 输入框 -->
            <div class="input">
                <textarea></textarea>
            </div>
            <!-- 按钮 -->
            <div class="btn">
                <input type="button" value="发送">
            </div>
        </div>
    </div>

    <iframe src="" frameborder="0"></iframe>

    <script type="text/template">
        <div class="self">
            <h5>我说</h5>
            <p>你好</p>
        </div>
        <div class="other">
            <h5>对方说</h5>
            <p>你好</p>
        </div>
    </script>
    <!-- 小技巧:先写模板,在模板中直接使用一些变量名,这些都是将来传给模板的对象属性 -->
    <!-- 准备模板 -->
    <script type="text/template" id="tmp">
        {{ if flag == 'self'}} 
            <div class="self">
                <h5>我说:</h5>
                <p>{{ msg }}</p>
            </div>
        {{ else }}
            <div class="other">
                <h5>对方说:</h5>
                <p>{{ msg }}</p>
            </div>
        {{ /if }}
    </script>

    <script src="../../jquery-1.12.4.min.js"></script>
    <!-- 引入模板引擎插件 -->
    <script src="../../template-web.js"></script>
    <script>
        //1-点击按钮,获取输入框中值,添加到聊天窗口
        //2-向后台发送请求,等待后他返回聊天内容
        //3-将后台返回聊天内容,添加到聊天窗口中
        $('.btn input').click(function () {
            var txt = $('textarea').val(); //txt只是一个字符串,模板需要数据是对象
            // 包装
            var data = {
                flag: 'self',
                msg: txt
            }

            //组合
            var str = template('tmp', data);
            $('.messages').append(str);
            //清空输入框
            $('textarea').val('');

            //向后台发送请求,等待后他返回聊天内容
            $.ajax({
                type: 'post',
                url: 'http://www.tuling123.com/openapi/api',
                dataType: 'json',
                data:{
                    key:'7e3ff98681194706b84b0338016ed987',
                    info: txt,                  
                    loc: '上海',
                    userid: '123456'
                },
                success: function (info) {
                    console.log(info);
                    var data = {
                        flag: 'other',
                        msg: info.text
                    }
                    //生成结构
                    $('.messages').append( template('tmp', data) );

                    if (info.url) {
                        // window.open(info.url);
                        $('iframe').attr('src', info.url);
                    }

                    if (info.list) {
                        $('iframe').attr('src', info.list[0].detailurl);
                    }
                }
            })

        })      
    </script>

</body>
</html>

其他的跨域手段(没卵用)

以下方式基本不用,了解即可:

1、顶级域名相同的可以通过domain.name来解决,即同时设置 domain.name = 顶级域名(如example.com)
2、document.domain + iframe
3、window.name + iframe
4、location.hash + iframe
5、window.postMessage()

其他跨域方式


虚拟主机配置

在一台web服务器上,我们可以通过配置虚拟主机,然后分别设定根目录,实现对多个网站的管理。

具体步骤如下:

1.找到http.conf文件

找到470行,去掉#号注释

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

2.找到httpd-vhosts.conf文件

在目录:D:\phpStudy\Apache\conf\extra下找到httpd-vhosts.conf文件

猜你喜欢

转载自www.cnblogs.com/jianjie/p/12383846.html
今日推荐