初识jsonp
jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案。很多时候我们需要在客户端获取服务器数据进行操作,一般我们会使用ajax+webservice做此事,但是如果我们希望获取的数据和当前页面并不是一个域,著名的同源策略(不同域的客户端脚本在没明确授权的情况下,不能读写对方的资源)会因为安全原因决绝请求,也就是我们不能向其它域直接发送请求以获取资源。
在localhot域上有一个books.php,里面包含脚本对test.com域的books.php发送get请求,希望获取其book列表资源,这就是一个跨域请求资源
$.ajax({
type:'get',
url:'http://test.com/books.php'
});
页面会报一个这样的错误:XMLHttpRequest cannot load http://test.com/books.php. Origin http://localhost is not allowed by Access-Control-Allow-Origin.jsonp是为了解决这个问题出现的。
jsonp原理
虽然有同源策略的限制,但是并不是HTML上所有资源都必须是同一个域的,我们常见的页面为了节省流量或加载速度采用Google或微软的 jQuery CDN,在页面上我们可以这样写就可以引用jQuery了
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
</script>
iframe、img、style、script等元素的src属性可以直接向不同域请求资源,jsonp正式利用script标签跨域请求资源的
简单实现
localhost的books.php希望获得域test.com的books列表,在域test.com内book列表存储在books.xml中
test.com/books.xml
<?xml version="1.0"?>
<books>
<book name="JavaScript: The Defiitive Guide" publisher="O'Reilly Media, Inc.">
<author>David Flanagan</author>
</book>
<book name="PHP anf MySQL Web Development" publisher="Perason Education">
<author>Luke Welling</author>
<author>Laura Thomson</author>
</book>
<book name="HTTP: The Defiitive Guide" publisher="O'Reilly Media, Inc.">
<author>David Courley</author>
<author>Brian Totty</author>
</book>
</books>
明显JavaScript不能直接获取books.xml,在test.com中需要有一个机制将xml转化为json(这也就是为什么叫jsonp,其实和ajax一样,返回的数据不一定是json格式,只是json很好用),并动态拼接一条javascript调用语句返回,这个例子中直接使用php页面拼接
test.com/bookservice.php
<?php
$path=$_SERVER["DOCUMENT_ROOT"].'/books.xml';
$json=json_encode(simplexml_load_file($path)); $callbackFn=$_GET['callback'];
echo "$callbackFn($json);";
?>
这样首先把xml文件内容转换成一个json对象
{"book":[
{"@attributes":{"name":"JavaScript: The Defiitive Guide","publisher":"O'Reilly Media, Inc."},"author":"David Flanagan"},
{"@attributes":{"name":"PHP anf MySQL Web Development","publisher":"Perason Education"},"author":["Luke Welling","Laura Thomson"]},
{"@attributes":{"name":"HTTP: The Defiitive Guide","publisher":"O'Reilly Media, Inc."},"author":["David Courley","Brian Totty"]}
]}
然后拼接为一条javascript语句交给localhost去处理,当然test.com并不知道应该拼接的方法名叫什么,需要localhost在发送请求的时候在url中传入一个叫callback(这个也随便,两边同步就行)的参数指明。看看localhost怎么发送请求吧
localhost/books.php
<!DOCTYPE html>
<html>
<head>
<title>Books</title>
<?php include('/components/headerinclude.php');?></head>
<style type="text/css">
.book-title
{
font-size: 15px;
font-weight:bold;
margin-top:6px;
} .book-info
{
color:#ccc;
font-style:italic;
border-bottom:dashed 1px #ccc;
}
</style>
</head>
<body>
<div style="margin:20px;">
<div style="font-size:16px;font-weight:bold;">Books</div>
<div id="books"> </div>
</div>
</body>
</html>
我们希望在id为books的div中展示所有book,先添加一个用以显示book的javascript函数,也就是获取到数据后的回调函数,结合上面拼接的json格式可以这么写
function displayBooks(books){
var books=books.book;
var booksContainer=document.getElementById('books');
for(var i=0;i<books.length;i++){
var tmp=Array();
tmp.push('<div class="book-title">'+books[i]['@attributes'].name+'</div>');
tmp.push('<div class="book-info">');
tmp.push('<div>Publisher: '+books[i]['@attributes'].publisher+'</div>');
tmp.push('<div>Author(s): ');
if(typeof books[i].author=='string'){
tmp.push(books[i].author);
}else{
var authors=books[i].author;
for(var j=0;j<authors.length;j++){
tmp.push(authors[j]+' ');
}
}
tmp.push('</div>'); //end of author
tmp.push('</div>'); //end of book info
booksContainer.innerHTML+=tmp.join('');
}
}
然后是关键的jsonp请求的方法了
function getBooks(){
var script=document.createElement('script');
script.setAttribute('type','text/javascript');
script.setAttribute('src','http://test.com/bookservice.php?callback=displayBooks');
document.body.appendChild(script);
} getBooks();
在getbooks()方法中动态创建了一个script标签,设置其src为test.com提供的获取数据的service接口并传入回调函数,这样我们可以看看页面的反应,在Chrome控制台下可以看到这条请求
这样我们就可以在localhost下获取test.com的books了
jquery实现
在jquery中也有对jsonp的封装,不过jquery把其放到了ajax中,不明白为什么,毕竟这东西和ajax不太一样。写一个jQuery版的
function getBooks(){
$.ajax({
type:'get',
url:'http://test.com/bookservice.php',
dataType:'jsonp',
jsonp:'callback',
jsonpCallback:'displayBooks'
});
}
看起来完全一样,不过方便了很多,不用自己创建script标签神马的了,指明dataType为jsonp,回调函数不放在url内了,而是使用两个参数分别指明。
安全性问题
当然使用jsonp会在一定程度上造成安全性问题,如果请求的站点不是信任站点,那么可能会在返回的方法调用中包含一些恶意代码。所以尽量向信任的站点发送请求。另外xss也经常会利用jsonp向站点注入恶意代码。
初识jsonp的更多相关文章
- 跨域问题解决方案(HttpClient安全跨域 & jsonp跨域)
1 错误场景 今天要把项目部署到外网的时候,出现了这样的问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 运行 都没有问题的, 一旦把我需要调用接口的项目B放到其他的服务器上, 就会 ...
- (三)ajax请求不同源之jsonp跨域
凡是拥有"src"这个属性的标签都具有跨域的能力,比如<script>.<img>.<iframe>. JS中,我们直接用XMLHttpRequ ...
- 跨域问题解决方式(HttpClient安全跨域 & jsonp跨域)
1 错误场景 今天要把项目部署到外网的时候,出现了这种问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 执行 都没有问题的, 一旦把我须要调用接口的项目B放到其它的server上, ...
- 《JavaScript修炼之道》读书笔记
1.参考书目 入门:<JavaScript DOM编程艺术>第二版 进阶:<JavaScript高级程序设计>第二版.<JavaScript编程精粹> <Ja ...
- jsonp、瀑布流布局、组合搜索、多级评论(评论树)、Tornado初识
1.JSONP原理剖析以及实现 1.1 同源策略限制 用django分别建立两个项目,jsonp01和jsonp02,然后再在这两个项目里分别建立一个app,比如名字叫jsonp1.jsonp2:js ...
- jsonp初识
我们在项目中对接口发起请求时会遇到一个跨域请求的问题,在这个时候,我们可以用一个较为简单的方法解决:jsonp 后端(以php为例): <?php header('Content-type: a ...
- vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结
vue—你必须知道的 目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...
- ajax技术初识与应用
一.ajax技术初识 AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术.Ajax不是一种新的编 ...
- python_way ,day22 tonardo,jsonp
python_way day22 1.tonardo 2.cookie 3.api认证 一.tonardo: a.tonardo 初识 #!/usr/bin/env python3# Created ...
随机推荐
- js跨域访问
什么是跨域 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦.这里把涉及到跨域的一些问题简单地整理一下: 首 ...
- textarea 在浏览器中固定大小和禁止拖动
HTML 标签 textarea 在大部分浏览器中只要指定行(rows)和列(cols)属性,就可以规定 textarea 的尺寸,大小就不会改变,不过更好的办法是使用 CSS 的 height 和 ...
- response.setHeader()的用法
一秒刷新页面一次 response.setHeader("refresh","1"); 二秒跳到其他页面 response.setHeader("re ...
- IT小喇叭-企业品牌宣传、产品营销推广的首选
IT小喇叭-企业品牌宣传.产品营销推广的首选 IT小喇叭,成立于2015年6月初,成都芮嘉科技有限公司旗下产品,主要进行媒体资源整合.宣传报道:使移动互联网等相关企业的产品宣传.品牌营销变得更加方便. ...
- 详解在Visual Studio中使用git版本系统[转]
这篇教程的预期,是希望没有任何版本使用基础的新手也可以掌握,所以细节较多,不当之处,欢迎指正. 一 .安装 git 开发工具 如果要使用 git 进行版本管理,其实使用 git 命令行工具就完全足够了 ...
- HTTP版本进化过程
http版本之间的区别以及变化过程[更新中...]
- python3下安装Django
1.下载python3 https://www.Python.org/ 我下载的是Python3.5.1 选的 Windows x86-64 executable installer 2. 打开cmd ...
- 解决Canvas.toDataURL 图片跨域问题
如题,在将页面的图片地址进行本地输出时(Html2Canvas.js),因不同源存在跨域问题,会出现toDataURL访问权限问题: [Redirect at origin 'http://sub1. ...
- 获取基于Internet Explorer_Server的聊天窗口内容
假设在得到窗体中控件的句柄(通过SPY++)的前提下,如果是像文本框这种控件,只要用SendMessage就可得到文本了,但是对于聊天记录窗口却行不通(返回空值),因为那其实是一个内置浏览器Inter ...
- 【dubbo】消费者Consumer搭建
一.consumer搭建(可以web/jar) 1.新建Maven项目,groupId:com.dubbo.consumer.demo artifactId:demo projectName:dubb ...