首页 web前端 js教程 Jsonp解决ajax的跨域问题

Jsonp解决ajax的跨域问题

Apr 04, 2018 pm 02:20 PM
ajax javascript jsonp

这次给大家带来Jsonp解决ajax的跨域问题,Jsonp解决ajax跨域问题的注意事项有哪些,下面就是实战案例,一起来看一下。

一、介绍

最近跨域问题比较多,而且自己刚好也看到这一块,就总结了一下,关于JSONP的东西百度的话东西确实很多,很多人都是复制别人的,如此下去,其实找的资料就那么几份,关键是我还看不懂,可能是能力问题吧,自己经过很多尝试,所以总结了一下,终究还是弄懂了皮毛。注意一点是,这里是用Jsonp解决ajax的跨域问题,具体的实现其实不是ajax。

1、同源策略

浏览器有一个很重要的概念——同源策略(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(JavaScript、ActionScript)在没明确授权的情况下,不能读写对方的资源。

2、JSONP

JSONP(JSON with Padding)是JSON的一种”使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的script 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。</p> <p style="text-align: left;"><span style="color: #ff0000"><strong>二、实践</strong></span></p> <p style="text-align: left;"><strong>1、模拟跨域请求</strong></p> <p style="text-align: left;">在本机弄两个tomcat,端口分别为8080,8888,也就满足了非同源的条件,那么要是从一个端口发送ajax去获取另外一个端口的数据,那么肯定会报跨域请求问题。</p> <p style="text-align: left;"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/6aa998e4d2edca235a11c4aef7eb7a24-0.png" class="lazy" title="" alt="这里写图片描述"></p> <p style="text-align: left;">这里有两个项目,分别是jsonp(8080),other(8888),在jsonp项目中index.jsp如下:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot; pageEncoding=&quot;UTF-8&quot;%&gt; &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;Insert title here&lt;/title&gt; &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.min.js&quot;&gt;&lt;/script&gt; &lt;script type=&quot;text/javascript&quot;&gt; function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/index.jsp', type:'post', dataType:'text', success:function(data){ console.log(data); } }); } &lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;input type=&quot;button&quot; value=&quot;jsonp&quot; onclick=&quot;jsonp_fun()&quot;/&gt; &lt;/body&gt; &lt;/html&gt;</pre><div class="contentsignin">登录后复制</div></div> <p style="text-align: left;">other(8888)项目中index.jsp如下:// 因为jsp实际就是servlet,这里就用jsp代替servlet演示。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot; pageEncoding=&quot;UTF-8&quot;%&gt; &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;Insert title here&lt;/title&gt; &lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.min.js&quot;&gt;&lt;/script&gt; &lt;/head&gt; &lt;body&gt; other domain &lt;/body&gt; &lt;/html&gt;</pre><div class="contentsignin">登录后复制</div></div> <p style="text-align: left;">其实中上面看无非就是jsonp页面中点击按钮ajax去获取other页面中的数据。</p> <p style="text-align: left;">结果如下:chrome控制台</p> <p style="text-align: left;"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/6aa998e4d2edca235a11c4aef7eb7a24-1.png" class="lazy" title="" alt="这里写图片描述"></p> <p style="text-align: left;">XMLHttpRequest cannot load http://localhost:8888/other/index.jsp. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.</p> <p style="text-align: left;">以上提示就是指跨域问题,不能从8080这个域去访问8888域的资源。</p> <p style="text-align: left;"><strong>2、利用script标签去访问other域的js文件</strong></p> <p style="text-align: left;">由于<script>标签的src是支持跨域请求的。最常见的就是CDN服务的应用啦,比如我项目中,如果想用jQuery,但是就没有这个js文件,去下载要找很久,而且版本还不知道下的对不对,那么可以百度搜jquery cdn,我随便找一个,比如bootstrap的cdn:http://www.bootcdn.cn/jquery/,有很多版本供你选择,只要在项目中加上就行了,最大缺点的话就是你没网的话,就引入不到啦。</p> <p style="text-align: left;"><strong>2.1 在other根路径创建js/other.js文件,</strong>内容如下:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">alert(&quot;this is other(8888) js&quot;);</pre><div class="contentsignin">登录后复制</div></div> <p style="text-align: left;"><strong>2.2 在jsonp/index.jsp中,加入script标签,引入other的js</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&lt;script type=&quot;text/javascript&quot; src=&quot;http://localhost:8888/other/js/other.js&quot;&gt;&lt;/script&gt;</pre><div class="contentsignin">登录后复制</div></div> <p style="text-align: left;">进入http://localhost:8080/jsonp/index.jsp,会立马弹出alert,表示引入的js文件自动执行了,跨域请求js成功。</p> <p style="text-align: left;"><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/6aa998e4d2edca235a11c4aef7eb7a24-2.png" class="lazy" title="" alt="这里写图片描述"></p> <p style="text-align: left;"><strong>2.3 同样的,直接引用,会立马执行立马的alert</strong>,那么在other.js中写函数,同样jsonp/index.jsp中也能调用到,这点就不演示了,项目开发中大多都是这样做的,页面与js/css分离。</p> <p style="text-align: left;"><strong>2.4 另外说明一点,</strong>如果在other.js中有函数通过ajax调用8080中的东西,然后引入之后,调用这个函数,也是可以的,但是如果other.js中函数ajax调用8888的东西,引入之后,调用这个函数,同样是跨域的。</p> <p style="text-align: left;"><strong>3、script实现跨域请求</strong></p> <p style="text-align: left;"><strong>3.1 简单模拟服务器返回数据</strong></p> <p style="text-align: left;">将jsonp/index.jsp改成如下:这里注意引入的other.js的位置,是在函数getResult之后的,如果在它之前的话,会提示函数不存在。js加载顺序是从上开始,在之前调用没创建的,不能成功。注意这里是指引入的js文件,如果是同一个js文件或者当前页面的js中,先执行调用,然后再写函数也是没有问题的,但是如果先执行调用引入js文件中的函数,然后再引入js文件,就会提示函数不存在。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script>

登录后复制

然后other.js

getResult({"result":"this is other domain's data"});

也就是在jsonp/index.jsp页面写好函数,然后引入其他域的js传入参数去调用这个函数,这里的参数你可以先看做是其他域服务器的接口返回的数据。

刷新页面,效果当然是

弹出alert框,this is other domain's data

3.2 模拟接口访问

看到这里,你会不会还是想不懂,上面js弄啥的,传个死的数据,有什么实际意义吗?,其实script的src不仅可以接js的地址,还可以接servlet的地址,也就是http接口地址,所以接下来,懒得写servlet,这里还是写jsp当做接口,在other项目中新建other.jsp页面,内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String params = request.getParameter("params");
out.println("ajax cross success,the server receive params :"+params);
%>
登录后复制

内容很简单,也就是接受一个params的参数,然后返回数据给调用者。

我们在jsonp/index.jsp中加上

<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>
登录后复制

看到这个地址,你是不是很熟悉,不熟悉的证明你用servlet用蠢了,jsp也是servlet,流程就是页面一加载的时候,script标签就会去发送请求,然后返回数据。那么我们刷新页面,看看效果。

这里写图片描述

Uncaught SyntaxError: Unexpected identifier

报错了,如上,然后代码有问题?No,点击错误,你会看到请求的东西也打印出来了,就是提示错误,表示这个东西浏览器不认识,其实是script不认识啦。

这里写图片描述

还不明白,那么你去页面加上如下内容,你看报不报错!!肯定报错

<script type="text/javascript">
ajax cross success,the server receive params : jsonp_param
</script>
登录后复制

那么js不能解析,我们换一种思路,要是我们输出的是JSON字符串或者调用当前页面函数的字符串了,类似于3.1中返回的getResult({“result”:”this is other domain's data”});

所以改造一下,把other.jsp中的内容改成

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String params = request.getParameter("params");
//out.println("ajax cross success,the server receive params :"+params);
out.println("getResult({&#39;result&#39;:&#39;"+params+"&#39;})");
%>
登录后复制

别忘了,之前jsonp/index.jsp中我们定义了,那么加入引用之后,依然记得getResult函数与引入函数的先后顺序问题。


<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>
登录后复制

刷新页面,发现大工告成。

这里写图片描述

至此,大部分原理已经讲完了,还有一个问题,这里服务器返回的是getResult(xxx),其中这里的xxx可以当做是经过接口的很多处理,然后塞进去的值,但是这个getResult这个函数名,调用方与其他域服务器这一方怎么约定这个名字是一致的了,况且很多公司自己做服务的,别的公司的开发人员去调用,难道每个人都去那么公司去约定调用函数的名字?怎么可能,所以有人就想出来了一种解决方案,当然不是我~~,其实也很简单啦,也就是把回调的函数名字也一起传过去不就行了,所以代码如下:

<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult"></script>
登录后复制

other.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String params = request.getParameter("params");
String callback = request.getParameter("callback");
// 经过该接口一系列操作,然后得到data,将data返回给调用者
String data = "{&#39;result&#39;:&#39;"+params+"&#39;}";
out.println(callback + "("+data+")");
%>
登录后复制

代码很简单,也就是传递一个回调函数的参数名,然后经过该接口一系列操作,将返回数据,塞到回调函数里面,调用端的函数就得到了该接口的数据,也就是类似于ajax中succsss:function(data),然后处理data一样,这里的success回调函数,相当于上面的getResult函数。当然你也可以写的优雅一点,比如:

function CreateScript(src) {
$("<script><//script>").attr("src", src).appendTo("body")
}
function jsonp_fun(){
CreateScript("http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult")
}
登录后复制

4、Jquery的JSONP

至此跨域请求的原理已经讲清楚了,但是仍然还有一个问题,总觉得这样用有点怪是不是,如果用jquery的话,调用就很简单了,其实jquery底层实现也是拼了一个script,然后指定src这种方式,跟上面讲的一样,只是jquery封装了一下,显得更加优雅,跟ajax调用方式差不多,所以容易记,代码如下:

<script type="text/javascript">
function getResult(data){
alert("through jsonp,receive data from other domain : "+data.result);
}
function jsonp_fun(){
$.ajax({
url:'http://localhost:8888/other/other.jsp',
type:'post',
data:{'params':'fromjsonp'},
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"getResult",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以不写这个参数,jQuery会自动为你处理数据
success: function(data){
},
error: function(){
alert('fail');
}
});
}
</script>
<body>
<input type="button" value="jsonp" onclick="jsonp_fun()"/>
</body>
登录后复制

这里的jsonCallback,回调函数设置为getResult,那么返回后会先调用getResult函数中的代码,再调用success函数中的代码,一般情况下,不用定义getResult函数,同样jsonCallback不需要设置,那么就只执行success中的代码,也就跟平时的ajax一样用啦。

所以实际工作用法如下:

function jsonp_fun(){
$.ajax({
url:'http://localhost:8888/other/other.jsp',
type:'post',
data:{'params':'fromjsonp'},
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
success: function(data){
alert("through jsonp,receive data from other domain : "+data.result);
},
error: function(){
alert('fail');
}
});
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String params = request.getParameter("params");
String callback = request.getParameter("callback");
// 经过该接口一系列操作,然后得到data,将data返回给调用者
String data = "{\"result\":\""+params+"\"}";
out.println(callback + "("+data+")");
%>
登录后复制

这里没有指定jsonpCallback,实际上jquery底层拼装了一个函数名,当然生成函数规则就没研究了。

这里写图片描述

补充:

1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;

2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

解决jQuery AJAX请求遇到403错误的方法 解决jQuery AJAX请求遇到403错误的方法 Feb 20, 2024 am 10:07 AM

标题:解决jQueryAJAX请求出现403错误的方法及代码示例403错误是指服务器禁止访问资源的请求,通常会导致出现这个错误的原因是请求缺少权限或者被服务器拒绝。在进行jQueryAJAX请求时,有时候会遇到这种情况,本文将介绍如何解决这个问题,并提供代码示例。解决方法:检查权限:首先要确保请求的URL地址是正确的,同时验证是否有足够的权限来访问该资

解决jQuery AJAX请求403错误的方法 解决jQuery AJAX请求403错误的方法 Feb 19, 2024 pm 05:55 PM

jQuery是一个流行的JavaScript库,用于简化客户端端的开发。而AJAX则是在不重新加载整个网页的情况下,通过发送异步请求和与服务器交互的技术。然而在使用jQuery进行AJAX请求时,有时会遇到403错误。403错误通常是服务器禁止访问的错误,可能是由于安全策略或权限问题导致的。在本文中,我们将讨论如何解决jQueryAJAX请求遭遇403错误

如何使用Ajax从PHP方法中获取变量? 如何使用Ajax从PHP方法中获取变量? Mar 09, 2024 pm 05:36 PM

使用Ajax从PHP方法中获取变量是Web开发中常见的场景,通过Ajax可以实现页面无需刷新即可动态获取数据。在本文中,将介绍如何使用Ajax从PHP方法中获取变量,并提供具体的代码示例。首先,我们需要编写一个PHP文件来处理Ajax请求,并返回所需的变量。下面是一个简单的PHP文件getData.php的示例代码:

如何解决jQuery AJAX报错403的问题? 如何解决jQuery AJAX报错403的问题? Feb 23, 2024 pm 04:27 PM

如何解决jQueryAJAX报错403的问题?在开发网页应用程序时,经常会使用jQuery来发送异步请求。然而,有时候在使用jQueryAJAX时可能会遇到错误代码403,表示服务器禁止访问。这种情况通常是由服务器端的安全设置所导致的,但可以通过一些方法来解决这个问题。本文将介绍如何解决jQueryAJAX报错403的问题,并提供具体的代码示例。一、使

PHP 与 Ajax:构建一个自动完成建议引擎 PHP 与 Ajax:构建一个自动完成建议引擎 Jun 02, 2024 pm 08:39 PM

使用PHP和Ajax构建自动完成建议引擎:服务器端脚本:处理Ajax请求并返回建议(autocomplete.php)。客户端脚本:发送Ajax请求并显示建议(autocomplete.js)。实战案例:在HTML页面中包含脚本并指定search-input元素标识符。

PHP 与 Ajax:创建动态加载内容的解决方案 PHP 与 Ajax:创建动态加载内容的解决方案 Jun 06, 2024 pm 01:12 PM

Ajax(异步JavaScript和XML)允许在不重新加载页面情况下添加动态内容。使用PHP和Ajax,您可以动态加载产品列表:HTML创建一个带有容器元素的页面,Ajax请求加载数据后将数据添加到该元素中。JavaScript使用Ajax通过XMLHttpRequest向服务器发送请求,从服务器获取JSON格式的产品数据。PHP使用MySQL从数据库查询产品数据,并将其编码为JSON格式。JavaScript解析JSON数据,并将其显示在页面容器中。点击按钮触发Ajax请求,加载产品列表。

PHP 与 Ajax:提高 Ajax 安全性的方法 PHP 与 Ajax:提高 Ajax 安全性的方法 Jun 01, 2024 am 09:34 AM

为了提升Ajax安全性,有几种方法:CSRF保护:生成令牌并将其发送到客户端,在请求中添加到服务器端进行验证。XSS保护:使用htmlspecialchars()过滤输入,防止恶意脚本注入。Content-Security-Policy头:限制恶意资源加载,指定允许加载脚本和样式表的来源。验证服务器端输入:验证从Ajax请求接收的输入,防止攻击者利用输入漏洞。使用安全Ajax库:利用jQuery等库提供的自动CSRF保护模块。

通过使用Ajax函数实现异步数据交换的方法 通过使用Ajax函数实现异步数据交换的方法 Jan 26, 2024 am 09:41 AM

如何利用Ajax函数实现异步数据交互随着互联网和Web技术的发展,前端与后端之间的数据交互变得十分重要。传统的数据交互方式,如页面刷新和表单提交,已经不能满足用户的需求。而Ajax(AsynchronousJavaScriptandXML)则成为了实现异步数据交互的重要工具。Ajax通过使用JavaScript和XMLHttpRequest对象,使得网

See all articles