文档章节

JSONP跨域GET请求解决Ajax跨域访问问题

文文1
 文文1
发布于 2015/12/04 15:40
字数 2143
阅读 824
收藏 11

需求:需要前端web页面异步调用后台的Webservice方法返回信息。

实现方法有多种,本例采用jQuery+Ajax,完成后,在本地调试了一切ok,但是部署到服务器上以后就出现问题了,后台服务调用没有响应,怎么回事?代码没怎么改动,唯一修改的地方就是jQuery的ajax方法中的url地址。难道是这里的问题,经过检查和调试,发现原来是同源策略在作怪,我们知道,JavaScript或jQuery是在Web前端开发中经常使用的动态脚本技术。在JavaScript中,有一个很重要的安全性限制,被称为“Same- Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档或脚本 在同一域名下的内容。不同域名下的脚本不能互相访问,即便是子域也不行。关于同源策略,读者可百度更详细的解释,这里不再赘述。

但是有时候又不可避免地需要进行跨域操作,这时候“同源策略”就是一个限制了,怎么办呢?采用JSONP跨域GET请求是一个常用的解决方案,下面我们来看一下JSONP跨域是如何实现的,并探讨下JSONP跨域的原理。

这里提到了JSONP,那有人就问了,它同JSON有什么区别不同和区别呢,接下我们就来看看,百度百科有以下说明:

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成(网络传输速度快)。

JSONP(JSON with Padding)是JSON的 一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。

到这里,应该明白了,JSON是一种轻量级的数据交换格式,像xml一样,是用来描述数据间的。JSONP是一种使用JSON数据的方式,返回的不是JSON对象,是包含JSON对象的javaScript脚本。

那JSONP是如何工作的呢,我们知道,由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。若要跨域请求出于安全性考虑是不行的,但是我们发现,Web页面上调用js文件时则不受是否跨域的影响,而且拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>,这时候,聪明的程序猿就想到了变通的方法,如果要进行跨域请求, 通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递 javascript对象。即在跨域的服务端生成JSON数据,然后包装成script脚本回传,着不就突破同源策略的限制,解决了跨域访问的问题了么。

下面我们就看下怎么实现:

function CallWebServiceByJsonp() {
        $("#SubEquipmentDetails").html('');
        $.ajax({
            type: "GET",
            cache: false,
            url: "http://servername/webservice/webservice.asmx/GetSingleInfo",
            data: { strCparent: $("#Equipment_ID").val() },
            dataType: "jsonp",
            //jsonp: "callback",
            jsonpCallback: "OnGetMemberSuccessByjsonp"
        });
}
function OnGetMemberSuccessByjsonp(data) {
    //处理data
    alert(data);
}

后端的WebService代码:

public void GetSingleInfo(string strCparent)
{
    string ret = string.Empty;
    HttpContext.Current.Response.ContentType = "application/json;charset=utf-8";
    string jsonCallBackFunName = HttpContext.Current.Request.Params["callback"].ToString();
    //string jsonCallBackFunName1 = HttpContext.Current.Request.QueryString["callback"].Trim();
    //上面代码必须
    //中间代码执行自己的业务操作,可返回自己的任意信息(多数据类型)
    BLL.equipment eq_bll = new BLL.equipment();
    List<Model.equipment> equipmentList = new List<Model.equipment>();
    equipmentList = eq_bll.GetModelEquimentList(strCparent);
    ret = JsonConvert.SerializeObject(equipmentList);
    //下面代码必须
    HttpContext.Current.Response.Write(string.Format("{0}({1})", jsonCallBackFunName, ret));
    HttpContext.Current.Response.End();
}

如上所示,前端的CallWebServiceByJsonp方法采用jQuery的ajax方法调用后端的Web服务GetSingleInfo方法,后台的GetSingleInfo方法,使用前端的回调方法OnGetMemberSuccessByjsonp包装后台的业务操作的JSON对象,返回给前端一段javascript片段执行。巧妙的解决了跨域访问问题。

JSONP的缺点:

JSONP不提供错误处理。如果动态插入的代码正常运行,你可以得到返回,但是如果失败了,那么什么都不会发生。

小伙伴们是否对JSONP跨域GET请求解决Ajax跨域访问问题有所了解了呢,本文的思路还是非常不错的,推荐给大家。

jquery ajax jsonp跨域调用实例代码

客户端代码:

<%@ 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.companyName;
      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="http://www.lagou.com/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: "http://www.lagou.com/join/listW3cplus?kd=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91",
     type: "GET",
     dataType: "jsonp",
     jsonpCallback: 'success_jsonpCallback',
     contentType: "application/jsonp; charset=utf-8",
     success: function(data) {
      success_jsonpCallback(data);
     }
    });
   }
   getLagouData();
        </script>
      <div id="lagouData"></div>

jsonp代码:

success_jsonpCallback([{"city":"广州","companyName":"POCO.CN","createTime":"15:02发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/16868.html","positionAdvantage":"身处凝聚力团队,老城区上班交通便利,双休","positionName":"商业前端开发工程师","salary":"4k-7k"},{"city":"北京","companyName":"美通云动(北京)科技有限公司","createTime":"14:47发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/16866.html","positionAdvantage":"Html5技术最棒的团队","positionName":"Web前端开发","salary":"4k-8k"},{"city":"杭州","companyName":"口袋购物","createTime":"14:42发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/13024.html","positionAdvantage":"广阔的发展平台、自我价值体现的地方","positionName":"web前端开发工程师","salary":"8k-12k"},{"city":"北京","companyName":"布丁移动","createTime":"14:02发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/1498.html","positionAdvantage":"三餐、周围美女如云","positionName":"Android开发工程师","salary":"10k-20k"},{"city":"北京","companyName":"布丁移动","createTime":"14:02发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/2539.html","positionAdvantage":"三餐,小桥流水人家,美女","positionName":"ios开发工程师","salary":"10k-20k"},{"city":"上海","companyName":"天天动听","createTime":"00:55发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/11494.html","positionAdvantage":"创业氛围 讲求小而美","positionName":"Android开发工程师","salary":"8k-16k"},{"city":"北京","companyName":"LBE安全大师","createTime":"11:39发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/5983.html","positionAdvantage":"五险一金 绩效奖金","positionName":"Android开发工程师","salary":"8k以上"},{"city":"北京","companyName":"点心移动","createTime":"11:24发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/16736.html","positionAdvantage":"技术导向的团队氛围,全方位的福利待遇","positionName":"Android","salary":"15k-25k"},{"city":"广州","companyName":"荔枝FM","createTime":"10:44发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/16634.html","positionAdvantage":"连坚持跑步、保持体重都有奖励哦!","positionName":"WP手机开发工程师","salary":"16k-25k"},{"city":"北京","companyName":"网银-京东子公司","createTime":"10:08发布","posiitonDetailUrl":"http://www.lagou.com:80/jobs/14162.html","positionAdvantage":"负责京东商城-互联网金融产品 JS开发","positionName":"Javascript 前端开发工程师","salary":"10k-20k"}])


本文转载自:

共有 人打赏支持
文文1
粉丝 21
博文 373
码字总数 119521
作品 0
长沙
程序员
私信 提问
加载中

评论(2)

文文1
文文1

引用来自“甩葱哥”的评论

建议不要在使用此方法,或者伴随promise来使用。jsonp因其原理,并不能使用同步模式。另外对restful风格接口不友好。相对应的,建议使用cors方案

感谢葱哥指导,这个我也是刚用,并不太熟悉的
甩葱哥
甩葱哥
建议不要在使用此方法,或者伴随promise来使用。jsonp因其原理,并不能使用同步模式。另外对restful风格接口不友好。相对应的,建议使用cors方案
juery的跨域请求2

时间过得好快,又被拉回js战场时, 跨域问题这个伤疤又开疼了. 好在,有jquery帮忙,跨域问题似乎没那么难缠了.这次也借此机会对跨域问题来给刨根问底,结合实际的开发项目,查阅了相关资料,算是解...

无信不立
2016/05/24
0
0
JSONP跨域的原理解析

JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页...

武文海
2016/03/21
24
0
看小白如何解决ajax跨域问题

由于此前很少写前端的代码(哈哈,不合格的程序员啊),最近项目中用到json作为系统间交互的手段,自然就伴随着众多ajax请求,随之而来的就是要解决ajax的跨域问题。本篇将讲述一个小白从遇到跨...

六只
2012/06/29
0
3
ajax和jsonp没有半点关系,跨域问题

jsonp确实和ajax没有半毛钱关系,只算是一种机制跨域数据获取方案或者协议。 只是说很多库(比如jquery)里面对jsonp和ajax做了一样的封装,看起来就好像jsonp是ajax的一部分一样,这好像会造...

SubinY
2016/12/26
32
0
JSON和JSONP的区别,以及使用方法

(一)场景 在拉京东城市选择的基础数据时候,遇到被服务器拒绝的情况,也就是ajax跨域问题 (二)json和jsonp 说的直白一点,在我们做ajax异步的一些功能的时候,一定会或多或少的遇到两个问...

taote
2013/11/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 你一口我一口多咬一口是小狗

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文 :分享Roy Orbison的单曲《She's a Mystery to Me》 《She's a Mystery to Me》- Roy Orbison 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
47分钟前
11
3
Spring源码学习笔记-1-Resource

打算补下基础,学习下Spring源码,参考书籍是《Spring源码深度解析》,使用版本是Spring 3.2.x,本来想试图用脑图记录的,发现代码部分不好贴,还是作罢,这里只大略记录下想法,不写太细了 ...

zypy333
今天
12
0
RestClientUtil和ConfigRestClientUtil区别说明

RestClientUtil directly executes the DSL defined in the code. ConfigRestClientUtil gets the DSL defined in the configuration file by the DSL name and executes it. RestClientUtil......

bboss
今天
18
0

中国龙-扬科
昨天
2
0
Linux系统设置全局的默认网络代理

更改全局配置文件/etc/profile all_proxy="all_proxy=socks://rahowviahva.ml:80/"ftp_proxy="ftp_proxy=http://rahowviahva.ml:80/"http_proxy="http_proxy=http://rahowviahva.ml:80/"......

临江仙卜算子
昨天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部