zoukankan      html  css  js  c++  java
  • 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 {
                 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 {
    			 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;
    			 100%;
    			height: 100%;
    			box-sizing: border-box;
    			border: none;
    			resize: none;
    			outline: none;
    			font-size: 20px;
    		}
    
    		.form input {
    			display: block;
    			 100px;
    			height: 30px;
    			margin-top: 5px;
    			margin-right: 20px;
    			float: right;
    		}
    
    		iframe {
    			position: absolute;
    			left: 10px;
    			top: 10px;
    			/* border: 1px solid green; */
    			 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:phpStudyApacheconfextra下找到httpd-vhosts.conf文件

  • 相关阅读:
    Python_函数
    Python中元组,列表,字典的区别
    Oracle 在字符串中输入单引号或特殊字符
    Visual Studio Code管理MySQL
    Python .pyc的编译和反编译
    Django 模板变量之 forloop
    浅谈Django基础(HttpResponse、render、redirect)
    Django 使用form表单提交数据报错: Forbidden (403)
    Django出错提示TemplateDoesNotExist at /
    使用 vs code 创建 Django 项目
  • 原文地址:https://www.cnblogs.com/jianjie/p/12383846.html
Copyright © 2011-2022 走看看