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文件

posted on 2020-02-29 17:11  冲啊!  阅读(239)  评论(0编辑  收藏  举报

导航