Jsonp跨域

Jsonp跨域请求

Featured image

jsonp跨域

同源策略

同源策略就是规定了javascript可以操作那些web内容的一个完整的安全限制。

什么是同源?

同源就是规定多个web资源的url中scheme、hostname、port必须相同,只要有一项不同那么这个web资源就不是同源的。同时,同源策略就会其相应的作用来限制这个web资源。

同源策略为什么会出现?

对于防止脚本窃取所有内容来说,同源策略是非常有必要的。如果没有这一个限制,恶意脚本可能会打开一个空页面,诱导用户进入并使用这个窗口在内网浏览操作文件。这样的话,恶意脚本就能够读取窗口内的内容发送到自己的服务器来达到窃取数据的目的。而同源策略就是限制了这种行为。

思考:web的安全性如何考虑?

跨域HTTP请求

什么是跨域?

当请求的资源的URL与当前页面的URL中的scheme、hostname、port有一个不同的时候就算是跨域操作。请参见上面的同源。

因为有同源策略的限制,XMLHttpRequest仅可以发起操作同域(同源)下的请求。虽然这个限制关闭了安全漏洞但是也阻止了大量合法的适合使用的跨域请求。不过这种情况下也可以在页面中使用img、form、iframe等元素中使用跨域URL,最中在浏览器中显示这些数据。但是因为同源策略,浏览器不允许操作或者不能良好的显示跨域文档内容。 如果此处使用XMLHttpRequest来操作跨域请求,那么所有的文档内容都将在responseText属性中暴露,所以同源策略不允许XMLHttpRequest进行跨域请求。 注意:img元素会把返回的内容强制转换为图片。iframe元素不允许操作跨域数据. 但是需要强调的是script元素并未真正受到同源策略的限制,因为script有可能需要加载不同域的javascript资源。需要加载并执行任何来源的脚本。正因为如此,script的灵活性使其成为在跨域操作中代替XMLHttpRequest的主流Ajax传输协议:JSONP。

JSONP

script元素可以作为一种Ajax传输协议,只需设置script元素的src属性并且插入到DOM中,浏览器就会发出一个HTTP请求到src属性所指向的URL。使用script元素进行Ajax传输的一个主要原因就是因为它不受同源策略的影响。因此可以发送一个不同源的请求。而另外一个原因就是用script元素会自动解码并执行(浏览器会当做javascript来处理)下载的数据。

JSONP带来的安全性考虑: 为了使用script元素来进行Ajax传输,你必须允许web页面信任并执行目标服务器返回过来的任何数据。这意味这对于不信任的服务器,不应该采取该技术。在与信任的服务器交互是还要提防攻击者可能会进入服务器中。所以作为Ajax数据传输的script与可信的服务器交互,是相当危险的事情。

使用这种script元素来进行Ajax数据的传输的技术就叫做’JSONP’,也就是JSON-padding.这个P(padding)代表的是 填充、补充、前缀。在于服务器返回的数据必须用javascript的方法名加括号包裹住才行。而不是仅仅发送一段JSON格式的数据而已,要是这样的话浏览器只会对返回的数据进行JSON解码,结果还是数据,并没有做任何相应的处理。 因此在使用JSONP的时候需要注意的是,服务器返回的数据是有固定格式的。例如:

​ //服务器不可以返回这样的数据

​ [“jeams”,”bond”,{NAME:”OBAMA”,AGE:56}]

​ //服务器会返回一个这样的响应

​ functionName([“jeams”,”bond”,{NAME:”OBAMA”,AGE:56}])

其中的functionName必须是在window下可以访问的名称。这样的话服务器就不仅仅只是返回一段JSON数据而已了,同时还会执行对应的操作。包裹后的响应会成为这个script元素的内容,它先判断JSON编码后的数据(因为是一个javascript表达式),然后把数据传给functionName函数。此处我们可以假设functionName会那这些数据做有用的事情。 但是为了可行起见,我们必须要把需要包裹数据的那个javascript方法名告诉服务器,也就是上面例子里的那个functionName。这样的话服务器就会知道用什么来包裹需要返回的数据了。服务器也可以知道返回的是一个JSONP数据而不是一个普通的JSON数据。例如可以在请求的URL后面加上?callback=functionName。

jsonp请求

原生js实现jsonp请求

利用script 的src特性

<script type="text/javascript">
	function callback(data){
        console.log(data);
	}
</script>
<script type="text/javascript" src="请求的url地址&callback=functionName"></script>

jquery实现jsonp请求

	<script type="text/javascript">
		$.ajax({
			url:"请求地址参数",  
			type:"get",    //请求方式
			dataType:"jsonp", //返回的数据
			data:null,   //传参
			timeout: 3000, //-->设定请求超时时间,一般设定3000ms
			async:true,   //异步执行
			cache: false, //-->设定Get请求的时候不走缓存数据,原理就是在URL末尾加随机数,默认值为true
			success: function (data){
				console.log("成功后的操作")
			}
			error: function (){
				console.log("请求失败后执行")
			}

		})
	</script>