Ajax-跨域-同源政策、Jsonp解决同源限制、CORS跨域资源共享

Ajax请求限制
Ajax 只允许向自己的服务器发送请求。

同源政策

同源:
多个页面拥有相同的协议域名和端口、否则不同源
多个页面、多个请求在同一个服务=同源
http和https是不相同的协议

同源政策的目的
同源政策是为了保证用户信息的安全,防止恶意的网站窃取数据。最初的同源政策是指A 网站在客户端设置的 Cookie,B网站是不能访问的。
因为同源政策的限制:不允许ajax向不同源服务端发送请求、浏览器拒收

JSONP 解决同源限制问题

jsonp 是 json with padding 的缩写,它不属于 Ajax 请求,但它可以模拟 Ajax 请求。

步骤

1、将不同源的服务器端请求地址写在 script 标签的 src 属性中。
<script src="www.example.com"></script>
<script src=“https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
2、服务器端响应数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数调用的参数。
 const data = 'fn({name: "张三", age: "20"})';
 res.send(data);
3、在客户端全局作用域下定义函数 fn。
	//将函数定义在服务器加载的前面
	function fn(data) {
	4、在 fn 函数内部对服务器端返回的数据进行处理。
		console.log('客服端函数被调用');
		console.log(data);	
	  }
//函数必须写在不同源服务请求的script前面

jsonp优化

1、客户端需要将函数名称传递到服务器
2、将script请求的发送编程动态请求
3、封装jsonp函数,方便请求发送
4、动态创建一个script标签
5、为script标签添加src属性 给封装函数传入对象参数
6、将script标签追加到页面中
7、在script标签完成后 把标签移除
8、因为发送的函数写在外面,导致封装性不好,所以把函数写在传递的参数对象中,需要注意的是在封装时把函数挂载在window中 使它变成全局的函数,还有一点要注意的是,在多个事件调用函数时前一个事件调用的函数可能会被后面事件调用的函数覆盖 所以在给函数命名时,使用随机命名
注意:这不是ajax请求、是模拟ajax
<script type="text/javascript">
		//点击提交按钮
 document.getElementById('btn1').onclick = function () {
			//请求非同源服务
			jsonp({
				url: 'http://localhost:3001/better',
				success: function (data) {
					console.log(123);
					console.log(data);

				}
			})
		}
	document.getElementById('btn2').onclick = function () {
			//请求非同源服务
			jsonp({
				url: 'http://localhost:3001/better',
				data:{
					name:'xiaoli',
					age:30
				},
				success: function (data) {
					console.log(1233333);
					console.log(data);

				}
			})
		}
		//封装 jsonp 函数,方便请求发送
		function jsonp(options) {
			//创建script标签
			var script = document.createElement('script');
			//准备把参数拼接为字符串的变量
			var params='';
			//遍历要传递的参数
			for(var attr in options.data){
				//以字符串形式拼接(参数名=参数值、多个参数之间用&隔开)
				params+='&'+attr+'='+options.data[attr];
				//拼接好后把参数放到请求的地址后面
			}
			//定义一个随机函数、挂载到window下、防止重名覆盖问题
			var fnName='myJsonp'+Math.random().toString().replace('.','');
			//把fn放入jsonp中、然后让它变成全局对象
			window[fnName] = options.success;
			//为script标签添加src属性
			script.src = options.url + '?callback='+fnName+params;
			//将script属性添加到页面中
			document.body.appendChild(script);
			//标签创建完后移除
			script.onload = function () {
				document.body.removeChild(script);
			}


		}

	</script>

//服务端代码优化
app.get('/better', (req, res) => {
	// 接收客户端传递过来的函数的名称
	//const fnName = req.query.callback;
	// 将函数名称对应的函数调用代码返回给客户端
	//const data = JSON.stringify({name: "张三"});
	//const result = fnName + '('+ data +')';
	// setTimeout(() => {
	// 	res.send(result);
	// }, 1000)
		//express方法
	res.jsonp({name: 'lisi', age: 20});
});


获取腾讯天气信息案例

<body>
	<div class="container">
		<table class="table table-striped table-hover" align="center" id="box">

		</table>
	</div>

</body>
<script src="/js/jsonp.js"></script>
<script src="/js/template-web.js"></script>
<script type="text/html" id="tpl">
	<tr>
	<!-- 创建天气模板、遍历天气数据 -->
			<th>时间</th>
			<th>温度</th>
			<th>天气</th>
			<th>风向</th>
			<th>风力</th>
		</tr>
		{{each info}}
		<tr>
	<!-- 创建天气模板、遍历天气数据 -->
			<td>{{dateFormat($value.update_time)}}</td>
			<td>{{$value.degree}}</td>
			<td>{{$value.weather}}</td>
			<td>{{$value.wind_direction}}</td>
			<td>{{$value.wind_power}}</td>
		</tr>
		{{/each}}
</script>
<script>
	//获取父元素
	var box=document.querySelector('#box');
	
       function dateFormat(data){
		 //  console.log(data);
		   
		   //截取年月日、时分秒
			var  year=data.substr(0,4);
			var  month=data.substr(4,2);
			var  day=data.substr(6,2);
			var  hour=data.substr(8,2);
			var  minute=data.substr(10,2);
			var  seconds=data.substr(12,2);
			let time=year+'年'+month+'月'+day+'日'+hour+'时'+minute+'分'+seconds+'秒';
			 return time ;	   
	  }
	//开放一个模板公共变量(必须是函数)
	template.defaults.imports.dateFormat=dateFormat;

	//向非同源服务器获取天气信息
	jsonp({
		url: 'https://wis.qq.com/weather/common',
		data: {
			source: 'pc',
			weather_type: 'forecast_1h',
			//多个数据调用
			// weather_type:'forecast_1h|forecast_24h',
			province: 'xx省',
			city: 'xx市'
		},
		success: function (data) {
		//模板拼接
		var html=template('tpl', { info: data.data.forecast_1h });
		console.log(html);
		box.innerHTML=html;
		

		}
	})
</script>
CORS 跨域资源共享

CORS:全称为 Cross-originresource sharing,即跨域资源共享,
服务端做配置然后允许浏览器向跨域服务器发送 Ajax 请求
在这里插入图片描述
请求过程
如果是跨域、客户端请求是会携带origin、服务端请求头配置了Access-Control-Allow-Origin的话就允许通过同源限制(相当于白名单)

 在服务端设置响应头
 	// 1.允许哪些客户端访问我
	// * 代表允许所有的客户端访问我
 	res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
	// 2.允许客户端使用哪些请求方法访问我
	res.header('Access-Control-Allow-Methods', 'get,post')
 //一般都设置在拦截所有请求的响应代码中 记得调用next方法向下传递

同源政策是浏览器对ajax技术的限制、服务端不存在同源限制

跨服务响应数据
a页面访问a服务、a服务访问b服务、然后在响应回a页面、
下载request第三方模块、使用返回的request方法

app.get('/server', (req, res) => {
//a服务访问b服务
	request('http://localhost:3001/cross', (err, response, body) => {
		res.send(body);
	})
});

cookie
客户端请求时,服务器响应 并且给客户端一个唯一的标识

在使用Ajax技术发送跨域请求时,默认情况下不会在请求中携带cookie信息

withCredentials://指定在涉及到跨域请求时,是否携带cookie信息 默认为false–客户端
Access-Control-Allow-Credentials: true//允许客户端发送请求时携带cookie --服务器端

	// 当发送跨域请求时携带cookie信息
			 xhr.withCredentials=true;
	// 允许客户端发送跨域请求时携带cookie信息
	res.header('Access-Control-Allow-Credentials', true);
这两个设置要同时设置 否则不会成功携带cookies
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值