有没有angularjs jsonp 跨域跨域的样例代码,包括服务器端代码

AJax与Jsonp跨域访问
您当前位置: &
[ 所属分类
| 时间 2015 |
作者 红领巾 ]
2.JQuery的AJax
3.利用jsonp实现跨域访问
####JavaScript的AJax
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML)
设计AJax使用的一种重要技术是XMLHttpRequest对象。
创建XMLHttpRequest对象的方式:
xmlhttp = new ActiveObject("Microsoft.XMLHTTP"); // IE浏览器支持的创建方式
xmlhttp = new XMLHTTPRequest(); // FireFox,Opera等浏览器支持的创建方式
XMLHttp是一套可以在Javascript、VbScript、Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API。可用于模拟http的GET和POST请求。
可以判断 window.XMLHttpRequest
对象是否可用然后创建XMLHttpRequest对象。
以下是XMLHttpRequest对象的属性和使用方法,粘贴过来的,注释的很详细。
&title&XMLHTTPRequest对象的说明DEMO&/title&
&script language="javascript" type="text/javascript"&
// 创建一个XMLHTTPRequest对象
function createXMLHTTPRequext(){
if(window.ActiveXObject) {
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
else if(window.XMLHTTPRequest){
xmlhttp = new XMLHTTPRequest();
function PostOrder(xmldoc)
createXMLHTTPRequext();
// 方法:open
// 创建一个新的http请求,并指定此请求的方法、URL以及验证信息
// 语法:oXMLHttpRequest.open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword);
// bstrMethod
// http方法,例如:POST、GET、PUT及PROPFIND。大小写不敏感。
// bstrUrl
// 请求的URL地址,可以为绝对地址也可以为相对地址。
// varAsync[可选]
// 布尔型,指定此请求是否为异步方式,默认为true。如果为真,当状态改变时会调用onreadystatechange属性指定的回调函数。
// bstrUser[可选]
// 如果服务器需要验证,此处指定用户名,如果未指定,当服务器需要验证时,会弹出验证窗口。
// bstrPassword[可选]
// 验证信息中的密码部分,如果用户名为空,则此值将被忽略。
// 备注:调用此方法后,可以调用send方法向服务器发送数据。
xmlhttp.Open("get", "http://localhost/example.htm", false);
// var book = xmlhttp.responseXML.selectSingleNode("//book[@id='bk101']");
// alert(book.xml);
// 属性:onreadystatechange
// onreadystatechange:指定当readyState属性改变时的事件处理句柄
// 语法:oXMLHttpRequest.onreadystatechange = funcMyH
// 如下的例子演示当XMLHTTPRequest对象的readyState属性改变时调用HandleStateChange函数,
// 当数据接收完毕后(readystate == 4)此页面上的一个按钮将被激活
// 备注:此属性只写,为W3C文档对象模型的扩展.
xmlhttp.onreadystatechange= HandleStateC
// 方法:send
// 发送请求到http服务器并接收回应
// 语法:oXMLHttpRequest.send(varBody);
// 参数:varBody (欲通过此请求发送的数据。)
// 备注:此方法的同步或异步方式取决于open方法中的bAsync参数,如果bAsync == False,此方法将会等待请求完成或者超时时才会返回,如果bAsync == True,此方法将立即返回。
// This method takes one optional parameter, which is the requestBody to use. The acceptable VARIANT input types are BSTR, SAFEARRAY of UI1 (unsigned bytes), IDispatch to an XML Document Object Model (DOM) object, and IStream *. You can use only chunked encoding (for sending) when sending IStream * input types. The component automatically sets the Content-Length header for all but IStream * input types.
// 如果发送的数据为BSTR,则回应被编码为utf-8, 必须在适当位置设置一个包含charset的文档类型头。
// If the input type is a SAFEARRAY of UI1, the response is sent as is without additional encoding. The caller must set a Content-Type header with the appropriate content type.
// 如果发送的数据为XML DOM object,则回应将被编码为在xml文档中声明的编码,如果在xml文档中没有声明编码,则使用默认的UTF-8。
// If the input type is an IStream *, the response is sent as is without additional encoding. The caller must set a Content-Type header with the appropriate content type.
xmlhttp.Send(xmldoc);
// 方法:getAllResponseHeaders
// 获取响应的所有http头
// 语法:strValue = oXMLHttpRequest.getAllResponseHeaders();
// 备注:每个http头名称和值用冒号分割,并以\r\n结束。当send方法完成后才可调用该方法。
alert(xmlhttp.getAllResponseHeaders());
// 方法:getResponseHeader
// 从响应信息中获取指定的http头
// 语法:strValue = oXMLHttpRequest.getResponseHeader(bstrHeader);
// 备注:当send方法成功后才可调用该方法。如果服务器返回的文档类型为"text/xml", 则这句话
// xmlhttp.getResponseHeader("Content-Type");将返回字符串"text/xml"。可以使用getAllResponseHeaders方法获取完整的http头信息。
alert(xmlhttp.getResponseHeader("Content-Type")); // 输出http头中的Content-Type列:当前web服务器的版本及名称。
document.frmTest.myButton.disabled =
// 方法:abort
// 取消当前请求
// 语法:oXMLHttpRequest.abort();
// 备注:调用此方法后,当前请求返回UNINITIALIZED 状态。
// xmlhttp.abort();
// 方法:setRequestHeader
// 单独指定请求的某个http头
// 语法:oXMLHttpRequest.setRequestHeader(bstrHeader, bstrValue);
// 参数:bstrHeader(字符串,头名称。)
// bstrValue(字符串,值。)
// 备注:如果已经存在已此名称命名的http头,则覆盖之。此方法必须在open方法后调用。
// xmlhttp.setRequestHeader(bstrHeader, bstrValue);
function HandleStateChange()
// 属性:readyState
// 返回XMLHTTP请求的当前状态
// 语法:lValue = oXMLHttpRequest.readyS
// 备注:变量,此属性只读,状态用长度为4的整型表示.定义如下:
// 0 (未初始化) 对象已建立,但是尚未初始化(尚未调用open方法)
// 1 (初始化) 对象已建立,尚未调用send方法
// 2 (发送数据) send方法已调用,但是当前的状态及http头未知
// 3 (数据传送中) 已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误,
// 4 (完成) 数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据
if (xmlhttp.readyState == 4){
document.frmTest.myButton.disabled =
// 属性:responseBody
// 返回某一格式的服务器响应数据
// 语法:strValue = oXMLHttpRequest.responseB
// 备注:变量,此属性只读,以unsigned array格式表示直接从服务器返回的未经解码的二进制数据。
alert(xmlhttp.responseBody);
// 属性:responseStream
// 以Ado Stream对象的形式返回响应信息
// 语法:strValue = oXMLHttpRequest.responseS
// 备注:变量,此属性只读,以Ado Stream对象的形式返回响应信息。
alert(xmlhttp.responseStream);
// 属性:responseText
// 将响应信息作为字符串返回
// 语法:strValue = oXMLHttpRequest.responseT
// 备注:变量,此属性只读,将响应信息作为字符串返回。XMLHTTP尝试将响应信息解码为Unicode字符串,
// XMLHTTP默认将响应数据的编码定为UTF-8,如果服务器返回的数据带BOM(byte-order mark),XMLHTTP可
// 以解码任何UCS-2 (big or little endian)或者UCS-4 数据。注意,如果服务器返回的是xml文档,此属
// 性并不处理xml文档中的编码声明。你需要使用responseXML来处理。
alert(xmlhttp.responseText);
// 属性:responseXML
// 将响应信息格式化为Xml Document对象并返回
// 语法:var objDispatch = oXMLHttpRequest.responseXML;
// 备注:变量,此属性只读,将响应信息格式化为Xml Document对象并返回。如果响应数据不是有效的XML文档,
// 此属性本身不返回XMLDOMParseError,可以通过处理过的DOMDocument对象获取错误信息。
alert("Result = " + xmlhttp.responseXML.xml);
// 属性:status
// 返回当前请求的http状态码
// 语法:lValue = oXMLHttpRequest.
// 返回值:长整形标准http状态码,定义如下:
// Number:Description
// 100:Continue
// 101:Switching protocols
// 201:Created
// 202:Accepted
// 203:Non-Authoritative Information
// 204:No Content
// 205:Reset Content
// 206:Partial Content
// 300:Multiple Choices
// 301:Moved Permanently
// 302:Found
// 303:See Other
// 304:Not Modified
// 305:Use Proxy
// 307:Temporary Redirect
// 400:Bad Request
// 401:Unauthorized
// 402:Payment Required
// 403:Forbidden
// 404:Not Found
// 405:Method Not Allowed
// 406:Not Acceptable
// 407:Proxy Authentication Required
// 408:Request Timeout
// 409:Conflict
// 410:Gone
// 411:Length Required
// 412:Precondition Failed
// 413:Request Entity Too Large
// 414:Request-URI Too Long
// 415:Unsupported Media Type
// 416:Requested Range Not Suitable
// 417:Expectation Failed
// 500:Internal Server Error
// 501:Not Implemented
// 502:Bad Gateway
// 503:Service Unavailable
// 504:Gateway Timeout
// 505:HTTP Version Not Supported
// 备注:长整形,此属性只读,返回当前请求的http状态码,此属性仅当数据发送并接收完毕后才可获取。
alert(xmlhttp.status);
// 属性:statusText
// 返回当前请求的响应行状态
// 语法:strValue = oXMLHttpRequest.statusT
// 备注:字符串,此属性只读,以BSTR返回当前请求的响应行状态,此属性仅当数据发送并接收完毕后才可获取。
alert(xmlhttp.statusText);
&form name="frmTest"&
&input name="myButton" type="button" value="Click Me" onclick="PostOrder('http://localhost/example.htm');"&
简单一点来说,就是利用XMLHttpRequest对象向服务器发出了请求,然后获取服务器返回信息这样一个过程,以上是JavaScript的Ajax技术原理。和后面要说的Jsonp实现跨域 访问的原理完全不一样。
###JQuery的AJax JQuery对ajax这种技术进行了封装,使用起来更为方便。$.ajax的一般形式
type: 'POST',
url: url ,
data: data ,
dataType: dataType
success: success ,
在场景不一样的时候,我们需要变换使用Ajax。 1.拼装json数据。 2.序列化表格内容。 var formParam = $("#form1").serialize();
3.拼接URL 。。。 比如我们的数据中有特殊字符串(比如&)的时候拼接字符串不好用,可能会使提交内容不完整。这时候采用Json的形式会比较好用。
###利用jsonp实现跨域访问
什么是Jsonp?
和json有什么关系?
jsonp是怎么实现跨域访问的?
首先解释一下,为什么Ajax不能跨域访问,浏览器为什么限制跨域访问。
假设浏览器支持跨域访问,我们可以在A站通过XmlHttpRequest访问B站,这时候已经通过了B站的验证,得到了B站的Cookie,然后我们就可以随意访问B站了,这时候A站冒用B站的身份可以操作B站一切不需要进一步验证的操作,这是相当危险的。
我们如何获取跨域的数据呢?
我们发现Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如script、img、iframe等等。我们可以利用js的这一性质来获取我们想要的数据。
为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
下面我们来看一下jsonp到底做了什么事情。
1、我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。 远程服务器根目录下有个remote.js文件代码如下:
alert('我是远程文件');
本地服务器下有个jsonp.html页面代码如下:
&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
&html xmlns="http://www.w3.org/1999/xhtml"&
&title&&/title&
&script type="text/javascript" src="/remote.js"&&/script&
毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。 这就是最基本的jsonp的思想。
2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。 jsonp.html页面代码如下:
&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
&html xmlns="http://www.w3.org/1999/xhtml"&
&title&&/title&
&script type="text/javascript"&
var localHandler = function(data){
alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
&script type="text/javascript" src="/remote.js"&&/script&
remote.js文件代码如下:
localHandler({"result":"我是远程js带来的数据"});
运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。 跨域访问数据的目的已经实现了,可是我怎么让远程js知道它应该调用的本地函数叫什么名字呢?
3.可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。
&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
&html xmlns="http://www.w3.org/1999/xhtml"&
&title&&/title&
&script type="text/javascript"&
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
在服务器端,我们获取callback,并且拼装好需要的js。
String callback = request.getParemeter("callback");
response.getWriter.print(callback + "(" + json +")");
这样返回给页面的内容是:
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
4.Jquery也对jsonp实现了封装。(形式比较像ajax)
&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
&html xmlns="http://www.w3.org/1999/xhtml" &
&title&Untitled Page&/title&
&script type="text/javascript" src=jquery.min.js"&&/script&
&script type="text/javascript"&
jQuery(document).ready(function(){
type: "get",
async: false,
url: "/jsonp/flightResult.aspx?code=CA1998",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
error: function(){
alert('fail');
最后申明,Ajax和jsonp是两个完全不一样的东西。 ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加script标签来调用服务器提供的js脚本。
【参考】 说说JSON和JSONP,也许你会豁然开朗
本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程
转载请注明本文标题:本站链接:
分享请点击:
1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
未长夜痛哭者,不足与语人生
手机客户端
,专注代码审计及安全周边编程,转载请注明出处:http://www.codesec.net
转载文章如有侵权,请邮件 admin[at]codesec.netjquery ajax jsonp跨域调用实例代码
字体:[ ] 类型:转载 时间:
今天研究了AJAX使用JSONP进行跨域调用的方法,发现使用GET方式和POST方式都可以进行跨域调用,这里简单分享下,方便需要的朋友
客户端代码
代码如下:&%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApp.WebForm1" %&&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&&html xmlns="http://www.w3.org/1999/xhtml" &&head runat="server"&&script src="jquery-1.7.1.min.js" type="text/javascript"&&/script&&script type="text/javascript"&&&& function aa() {&&&&&&& $.ajax({&&&&&&&&&&& url: "http://localhost:12079/WebForm2.aspx",&&&&&&&&&&& data: "p1=1&p2=2&callback=?",&&&&&&&&&&& type: "post",&&&&&&&&&&& processData: false,&&&&&&&&&&& timeout: 15000,&&&&&&&&&&& dataType: "jsonp",& // not "json" we'll parse&&&&&&&&&&& jsonp: "jsonpcallback",&&&&&&&&&&& success: function(result) {&&&&&&&&&&& alert(result.value1);&&&&&&&&&&& }&&&&&&& });&&& }&/script&&&& &title&&/title&&/head&&body&&&& &form id="form1" runat="server"&&&& &div&&&& &/div&&&& &/form&&&& &p&&&&&&&& &input id="Button1" type="button" value="button" onclick="aa()" /&&/p&&/body&&/html&
服务器端代码
代码如下:&public partial class WebForm2 : System.Web.UI.Page&&& {&&&&&&& protected void Page_Load(object sender, EventArgs e)&&&&&&& {&&&&&&&&&& &&&&&&&& string callback = Request["callback"]; &&&&&&&&&&& string v1="1";&&&&&&&&&&& string v2="2";&&&&&&&&&&& string response = "{\"value1\":\"" + v1 + "\",\"value2\":\"" + v2 + "\"}";&&&&&&&&&&& string call = callback + "(" + response + ")";&&&&&&&&&&& Response.Write(call);&&&&&&&&&&& Response.End();&&&&&&& }&&& }
客户端页面和服务器端页面在两个项目中,以便进行跨域调用测试。跨域实例代码(需要加载jquery,页面为utf-8编码):
代码如下:&&!--拉勾招聘数据--&&&&script type="text/javascript"&&&&function success_jsonpCallback(data){&&&&var html = '';&&&&var pos = '';&&&&html += '&ul&';&&&&jQuery.each(data, function(k, v) {&&&&&&&&&&&&&&&& if(k&10){&&&&&&&&&&&&&&&& &pos = '【' + v.city+ '】' + v.positionName + '('+ v.salary +') - '+v.companyN&&&&&&if(pos.length & 20){&&&&&&&pos = pos.substring(0,19)+'...';&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&& html += '&li&&a href="'+v.posiitonDetailUrl+'" target="_blank" title="【' + v.city+ '】' + v.positionName + '('+ v.salary +') - '+v.companyName+'"&'+pos+'&/a&&/li&';&&&&&&&&&&&&&&&& }&&&&});&&&&html += '&/ul&&div class="more-link"&&a href="/jobs/list_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91" target="_blank"&更多&/a&&/div&';&&&&jQuery('#lagouData').html(html);&&&}&&&function getLagouData() {&&&&jQuery.ajax({&&&&&async:false,&&&&&url: "/join/listW3cplus?kd=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91",&&&&&type: "GET",&&&&&dataType: "jsonp",&&&&&jsonpCallback: 'success_jsonpCallback',&&&&&contentType: "application/ charset=utf-8",&&&&&success: function(data) {&&&&&&success_jsonpCallback(data);&&&&&}&&&&});&&&}&&&getLagouData();&&&&&&& &/script&&&&&& &div id="lagouData"&&/div&
jsonp代码:
代码如下:success_jsonpCallback([{"city":"广州","companyName":"","createTime":"15:02发布","posiitonDetailUrl":":80/jobs/16868.html","positionAdvantage":"身处凝聚力团队,老城区上班交通便利,双休","positionName":"商业前端开发工程师","salary":"4k-7k"},{"city":"北京","companyName":"美通云动(北京)科技有限公司","createTime":"14:47发布","posiitonDetailUrl":":80/jobs/16866.html","positionAdvantage":"Html5技术最棒的团队","positionName":"Web前端开发","salary":"4k-8k"},{"city":"杭州","companyName":"口袋购物","createTime":"14:42发布","posiitonDetailUrl":":80/jobs/13024.html","positionAdvantage":"广阔的发展平台、自我价值体现的地方","positionName":"web前端开发工程师","salary":"8k-12k"},{"city":"北京","companyName":"布丁移动","createTime":"14:02发布","posiitonDetailUrl":":80/jobs/1498.html","positionAdvantage":"三餐、周围美女如云","positionName":"Android开发工程师","salary":"10k-20k"},{"city":"北京","companyName":"布丁移动","createTime":"14:02发布","posiitonDetailUrl":":80/jobs/2539.html","positionAdvantage":"三餐,小桥流水人家,美女","positionName":"ios开发工程师","salary":"10k-20k"},{"city":"上海","companyName":"天天动听","createTime":"00:55发布","posiitonDetailUrl":":80/jobs/11494.html","positionAdvantage":"创业氛围 讲求小而美","positionName":"Android开发工程师","salary":"8k-16k"},{"city":"北京","companyName":"LBE安全大师","createTime":"11:39发布","posiitonDetailUrl":":80/jobs/5983.html","positionAdvantage":"五险一金 绩效奖金","positionName":"Android开发工程师","salary":"8k以上"},{"city":"北京","companyName":"点心移动","createTime":"11:24发布","posiitonDetailUrl":":80/jobs/16736.html","positionAdvantage":"技术导向的团队氛围,全方位的福利待遇","positionName":"Android","salary":"15k-25k"},{"city":"广州","companyName":"荔枝FM","createTime":"10:44发布","posiitonDetailUrl":":80/jobs/16634.html","positionAdvantage":"连坚持跑步、保持体重都有奖励哦!","positionName":"WP手机开发工程师","salary":"16k-25k"},{"city":"北京","companyName":"网银-京东子公司","createTime":"10:08发布","posiitonDetailUrl":":80/jobs/14162.html","positionAdvantage":"负责京东商城-互联网金融产品 JS开发","positionName":"Javascript 前端开发工程师","salary":"10k-20k"}])
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具javascript中jsonp用法及跨域实例-jquery-网页制作-壹聚教程网javascript中jsonp用法及跨域实例jsonp专门是用来做跨域操作的了,下面小编整理了自己在学习jsonp是的几篇文章,希望这篇文章可以帮助到各位。
Asynchronous JavaScript and XML(Ajax)是目前 Web 开发关键技术之一,允许客户端 JavaScript 通过 HTTP 与服务器进行交互。
的安全模型规定了 XMLHttpRequest、frames 等必须在相同域名下才能进行通信。这就是所谓的&同源策略限制&。
为了 Web 应用的安全,同源策略并不是坏东西,但当我们真的需要请求其他域名下的数据时,这个策略确实造成了麻烦。
克服该限制的方法:
1、还是请求自己的服务器,让服务器做代理,把请求转发给真正的第三方服务器。这个方案的使用比较普遍,但一看上去就挺浪费的。
2、Flash。服务器上要部署一个 crossdomain.xml 文件,并将功能在 Flash 中开发,以达到跨域目的。但是要学习 AS 开发语言,成本较高。
3、通过 &script src=&&& 标签,进行脚本插入。标签中的脚本源指向第三方服务器,因为同源策略并不阻止标签中引进第三方服务器的脚本。通过 JSON 可以改进该方案。缺点在于:难调试、被不信任的服务使用时会存在危险。
JSONP 属于第 3 种方案。
JSONP(JSON with Padding)是一个非官方的协议,他的实现方式简单,但需要一点服务端的配合。大致就是:让客户端决定要回调的 Javascript 函数名,在第三方服务端将 JSON 数据拼装到回调函数名中,返回的就是参数为 JSON 数据的函数调用脚本,浏览器加载脚本,并执行,达到获取第三方数据的目的。下面是最初级的实现代码。
客户端代码:
&script type=&text/&&
function jsonpCallback(result) {
alert(result.a);
alert(result.b);
alert(result.c);
for(var i in result) {
alert(i+&:&+result[i]); //循环输出a:1,b:2,etc.
&script type=&text/javascript& src=&/services.php?callback=jsonpCallback&&&/script&
服务端 services.php 代码:
//服务端返回JSON数据
$data = array('a'=&1,'b'=&2,'c'=&3,'d'=&4,'e'=&5);
$result = json_encode($data);
$callback = $_GET['callback'];
echo $callback . &(& . $result . &)&; //动态执行回调函数
jQuery中的 $.getJSON $.ajax $.get 也有用到 JSONP,不知道大家注意到没。
首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。看起来不知道什么意思,实践一下就知道了。
1. 随便建两个网页
在你的的httpd.conf配置文件中添加如下配置:
Listen 11111
Listen 22222
namevirtualhost localhost:11111
namevirtualhost localhost:22222
&VirtualHost& localhost:11111&
ServerAdmin&&
ServerName&& localhost:11111
DocumentRoot&& E:/wamp/www/test/test11111
&/VirtualHost&
&Directory&& &E:/wamp/www/test/test11111&&
Options&& Indexes&& FollowSymLinks MultiViews
AllowOverride&& All
Order&& allow,deny
Allow&& from&& all
&/Directory&
&VirtualHost& localhost:22222&
ServerAdmin&&
ServerName&& localhost:22222
DocumentRoot&& E:/wamp/www/test/test22222
&/VirtualHost&
&Directory&& &E:/wamp/www/test/test22222&&
Options&& Indexes&& FollowSymLinks
AllowOverride&& None
Order&& allow,deny
Allow&& from&& all
&/Directory&
这样一个端口是11111,一个22222,按照定义它们是不同源的
&2. 用jQuery发起不同源的请求
在11111端口的网页上添加一个按钮,Click事件随便发起向端口为22222域的请求:
&&& &title&11111&/title&
&&& &button id=&get22222&&Click&/button&
&&& &script src=&/ajax//jquery-1.8.0.js& type=&text/javascript&&&/script&
&&& &script type=&text/javascript&&
&&&&&&& $(&#get22222&).click(function () {
&&&&&&&&&&& $.get(&http://localhost:22222/js/jquery.min.js&, function (data) {
&&&&&&&&&&&&&&& console.log(data)
&&&&&&&&&&& })
&&&&&&&&&&& $.get(&http://localhost:22222/index.php&, function (data) {
&&&&&&&&&&&&&&& console.log(data)
&&&&&&&&&&& })
&&&&&&& })
&&& &/script&
根据同源策略,很明显会悲剧了。浏览器会阻止,根本不会发起这个请求。
OK,原来jsonp是要解决这个问题的。
script标签的跨域能力
不知道大家知不知道CDN这个东西,例如微软的CDN,使用它,我们的网页可以不提供jQuery,由微软的网站帮我们提供:
&script src=&/ajax/jquery/jquery-1.8.0.js& type=&text/javascript&&&/script&
回到我们的11111端口的网页,上面我们在Click事件里有一个对22222端口域的jQuery文件的请求,这次使用script标签来请求。
&script type=&text/javascript& src=&http://localhost:22222/js/jquery.min.js&&&/script&
当然,200,OK了。
同样是端口11111的网页发起对22222域的请求,放在script里设置scr属性的OK了,另一个方式就悲剧。利用script的跨域能力,这就是jsonp的基础。
&利用script获取不同源的json
既然它叫jsonp,很明显目的还是json,而且是跨域获取。根据上面的分析,很容易想到:利用js构造一个script标签,把json的url赋给script的scr属性,把这个script插入到dom里,让浏览器去获取。实践
E:\wamp\www\test\test11111\index.phpPHP
&&& &title&11111&/title&
&&& &button id=&get22222&&Click&/button&
&&& &script src=&/ajax/jquery/jquery-1.8.0.js& type=&text/javascript&&&/script&
&&& &script type=&text/javascript&&
&&&&&&& function CreateScript(src) {
&&&&&&&&&&& $(&&script&&//script&&).attr(&src&, src).appendTo(&body&)
&&&&&&& $(&#get22222&).click(function () {
&&&&&&&&&&& CreateScript(&http://localhost:22222/index.php&);
&&&&&&& })
&&& &/script&
E:\wamp\www\test\test22222\index.phpPHP
$arr = array ('a'=&1,'b'=&2,'c'=&3,'d'=&4,'e'=&5);
echo json_encode($arr);
首先,第一个浏览器,http://localhost:22222/index.php这个Url的确是存在一个json的,而且在端口11111网页上用script标签来请求这个22222这个Url也是200OK的,但是最下面报js语法错误了。原来用script标签加载完后,会立即把响应当js去执行,很明显{&a&:1,&b&:2,&c&:3,&d&:4,&e&:5}不是合法的js语句。
利用script获取异域的jsonp
显然,把上面的json放到一个回调方法里是最简单的方法。例如,变成这样:
E:\wamp\www\test\test22222\index.phpPHP
$callback = $_GET['callback'];
$arr = array ('a'=&1,'b'=&2,'c'=&3,'d'=&4,'e'=&5);
echo $callback . '(' . json_encode($arr) . ')';
如果存在jsonpcallback这个方法,那么jsonpcallback({&a&:1,&b&:2,&c&:3,&d&:4,&e&:5})就是合法的js语句。
由于服务器不知道客户端的回调是什么,不可能hard code成jsonpcallback,所以就带一个QueryString让客户端告诉服务端,回调方法是什么,当然,QueryString的key要遵从服务端的约定,上面的是&callback&。
添加回调函数:
JavaScript
function jsonpcallback(json) {
& console.log(json)
把前面的方法稍微改改参数:
JavaScript
$(&#get22222&).click(function () {
& CreateScript(&http://localhost:22222/index.php?callback=jsonpcallback&);
200OK,服务器返回jsonpcallback({&a&:1,&b&:2,&c&:3,&d&:4,&e&:5}),我们也写了jsonpcallback方法,当然会执行。OK顺利获得了json。没错,到这里就是jsonp的全部。
利用jQuery获取jsonp
上面的方式中,又要插入script标签,又要定义一个回调,略显麻烦,利用jQuery可以直接得到想要的json数据,同样是上面的jsonp(服务器端代码不变):
E:\wamp\www\test\test11111\index.phpXHTML
&&& &title&11111&/title&
&&& &button id=&get22222&&Click&/button&
&&& &script src=&/ajax/jquery/jquery-1.8.0.js& type=&text/javascript&&&/script&
&&& &script type=&text/javascript&&
&&&&&&& $(&#get22222&).click(function () {
&&&&&&&&&&& $.ajax({
&&&&&&&&&&&&&&& url: 'http://localhost:22222/index.php',
&&&&&&&&&&&&&&& dataType: &jsonp&,
&&&&&&&&&&&&&&& jsonp: &callback&,
&&&&&&&&&&&&&&& success: function (data) {
&&&&&&&&&&&&&&&&&&& console.log(data)
&&&&&&&&&&&&&&& }
&&&&&&&&&&& })
&&&&&&& })
&&& &/script&
得到的结果跟上面一样。
一句话就是利用script标签绕过同源策略,获得一个类似这样的数据,jsonpcallback是页面存在的回调方法,参数就是想得到的json。
JavaScript
jsonpcallback({&a&:1,&b&:2,&c&:3,&d&:4,&e&:5})
到这里不免产生一个疑惑,同源策略是基于安全的原因建立的,发起不同源的请求是被认为不安全的,不可以接受的,但为什么这样绕一个小圈子就可以接受呢?这样就安全了吗?感觉就像洗澡时怕被人看见,把门关上,但侧面的大窗户却是打开的,这样做有意义吗?元芳你怎么看?
上一页: &&&&&下一页:相关内容
布丁动画小恩爱编辑推荐
电脑壁纸相关专题

我要回帖

更多关于 jsonp跨域的原理解析 的文章

 

随机推荐