JavaScript使用jsonp实现跨域
为什么要把ajax跨域写一下呢,因为ajax跨域并不是想跨就能跨的。因为为了安全,ajax是不允许跨域的。
举个例子,你有一个卖水果的网站,你的ajax请求另一个网站提供的图片,正常的时候,图片是一个苹果,但是那个网站被黑了,图片全被改为全是大便的同名文件,那么你请求回来的图片一显示,那场景,无限壮观。
一般情况下,只有自己的网站的内容才是可信的,其他外来的资源并不是完全可信的。比如平时开发中在script标签src中引入CDN的jquery文件,如果某一天,未通知你,CDN上的jquery文件被恶意篡改了,那你可能就凉了。
什么是域
域由三部分组成
1、协议(http、https、ftp....)
2、IP或者域名
3、端口
上面这三个部分,要是有一部分不同,就会出现跨域。
常用的跨域手段
Flash:使用flash插件完成,很少用,我没用过。
本地代理:既然ajax请求其他域名下的文件会失败,但是后端的程序请求其他域名的文件就不会存在跨域这个问题了吧,你可以在后端写一个程序,专门用来接收本地ajax对其他域资源的请求,然后代替ajax去请求资源,并且将其他域返回给后端的响应 再 返回给ajax,这样ajax就可以获取到其他域的资源了。虽然能达到目的,但是也请复杂的,很少采用。
接受请求端设置http头部信息。
Jsonp:经常使用,下面重点写。
通过设置头部信息实现跨域
以php为例,在接受方的程序中的header添加一项即可:
//接收所有跨域请求
header("Access-Control-Allow-Origin:*"); //接收来自某个ip的请求
header("Access-Control-Allow-Origin:192.168.1.2"); //接收来自某个域名的请求
header("Access-Control-Allow-Origin:www.demo.com");
jsonp
说jsonp之前,先说一下咱们平时使用的一些标签,比如script、img,他们都一个共同点———src属性。通过src属性,可以将其他资源包含进来,其中,src并不会有跨域的问题。
比如下面这段代码:
<script src="1.txt"></script>
1.txt的内容如下:
var a=10;
那么在接下来的JavaScript代码就可以访问从1.txt中获取到的变量a了,此时的a是全局变量。其实就等价于:
<script>
var a=10;
</script>
也许你已经猜到了,我们可以将src的值,也就是链接的地址改成其他域的资源名称,比如
<script src="https://www.baidu.com"></script>
这样的话,咱们就能将baidu首页包含进来。
但是,有一个很严峻的问题:你怎么使用获取的内容?
虽然已经将内容百度的首页内容引入了,相当于下面这样:
<script>
这是百度首页的代码
</script>
你怎么使用内容,很难头疼的。因为并没有像var a = 10那样为内容保存到变量中呀。
于是聪明的你,肯定想到了,既然包含的文件全是内容,并没有赋值给一个变量,所以我们无法使用。那么,我们可以让他在返回资源的时候 就 先将内容项赋值给一个变量 然后再一并返回。
既然是我们要请求其他域的资源,那么其他域肯定会提供这个功能的,不会说只是单纯的提供数据,如果只是单纯的提供数据,那么让他们加一下嘛,也就几分钟的事。
比如说下面这样:
<script src="demo.php"></script>
<script>
console.log(a);
</script>
demo.php内容如下:
<?php
$v = 10;
echo "var a = " . $v;
?>
然后JavaScript就会正常的运行。输出10。
上面简单的示例,只是返回一个简单的字符串,只不过该字符串是可以再浏览器中执行的JavaScript语句。但是也有个问题,返回的JavaScript语句中的变量是全局的,对不? 所以我们在想办法,怎么让返回的内容不变成全局的呢?
可以这么做:
<script>
function Work(data){
console.log(data);
}
</script>
<script src="demo.php"></script>
demo.php:
<?php
$v = 10;
echo "Work(". $v .")";
?>
可以看到,只是在请求其他域的资源之前先定义一个函数,该函数有参数。而在其他域被请求的文件中,返回一个字符串,字符串内容前一部分就是之前定义的JavaScript函数(这里是Work),以及将要传回的数据作为参数,内嵌到其中。
其实现在用的技术就是jsonp,不知不觉吧。这就是jsonp中p(padding填充的含义),而jsonp中的json就是平时的json,合起来的理解就是:填充的内容时json格式的数据,填充到一个js的函数名中,组合成字符串返回。
这里有几个注意点,
1、实现定义函数。
2、被请求资源中会返回的字符串中包含前面定义的函数。
还有一个问题:我们只是指定了src的链接,即请求谁,但是,我们没有指定什么时候指定。开发中,我们更重要的是在需要的时候在发起请求,即 按需加载。
注意这里不要在一个script标签中指定一个id,然后通过获取这个script之后,动态修改src值,来发起请求,这是错误的,因为一旦加载过的代码是不会再次执行的,除非你刷新页面。
正确的姿势是:创建一个dom元素节点(script),然后设置src之后,append到body中即可。
比如下面这个用法:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
function Work(data){
alert(data);
}
</script>
</head>
<body>
<button id="btn">request</button>
</body>
<script>
window.onload = function(){
var btn = document.getElementById("btn");
btn.onclick = function(){
var script = document.createElement("script");
script.src = "demo.php";
document.body.append(script);
}
}
</script>
</html>
demo.php
<?php
$v = 10;
echo "Work(". $v .")";
?>
运行时,一旦点击click按钮,就会创建一个script标签,加载src的内容,然后执行返回的数据。
还没完,上面的function Work()中是将获得的响应数据alert出来,但现在我们需要将相应数据console.log打印出来,咋办?找后端的RD再创建一个Work2(),返回的时候,将Work改为Work2 ???
如果你这样做,多半会被人家打死的。
其实你是可以将你要调用的function传递给后端,然后后端在处理完数据之后,返回你所传递的函数名,向下面这样:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
function WorkAlert(data){
alert(data);
}
function WorkConsoleLog(data){
console.log(data);
}
</script>
</head>
<body>
<button id="btn1">alert</button>
<button id="btn2">console.log</button>
</body>
<script>
window.onload = function(){
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
btn1.onclick = function(){
var script = document.createElement("script");
script.src = "demo.php?callback=WorkAlert"; //重点
document.body.append(script);
}
btn2.onclick = function(){
var script = document.createElement("script");
script.src = "demo.php?callback=WorkConsoleLog"; //重点
document.body.append(script);
} }
</script>
</html>
demo.php
<?php
//默认callback为WorkAlert
$callback = isset($_GET['callback']) ? $_GET['callback'] : "WorkAlert"; $v = 10;
echo $callback . "(" . $v . ")";
?>
下面是jsonp的一个使用示例,参考360的so.com,在输入框输入文字时,下拉框提示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>仿360搜索</title>
<style>
body{margin:0; padding:0;}
#container{margin:0 auto;height:100%; width:800px; text-align:center}
#div{margin:0 auto; margin-top:30%;}
#keyword{width:400px; height:40px; border-radius:5px; font-size:25px;}
#search{width:70px; height:40px; border-radius:10px;border:1px solid grey; line-height:40px; background: #19b955;}
li {list-style: none; border:1px solid grey; height:40px;border-radius:5px; text-align:left;}
</style>
</head>
<body>
<div id="container">
<div id="div">
<div>
<input type="text" name="keyword" id="keyword">
<input type="submit" value="搜索" id="search">
</div>
<ol id="opt"></ol>
</div>
</div>
</body>
<script>
function showData(data){
var res = data.result;
var length = res.length;
var Html = "";
for(var i = 0; i < length; i++){
Html += "<li>" + res[i].word + "</li>";
}
var opt = document.getElementById("opt");
opt.innerHTML = Html;
}
var keyword = document.getElementById("keyword");
keyword.oninput = function(){
var v = this.value;
var script = document.createElement("script");
script.src = "https://sug.so.360.cn/suggest?callback=showData&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word=" + v;
document.body.append(script);
}
</script>
</html>

各种跨域的比较
使用代理的话,没啥说的,可以,没有什么问题。
jsonp:因为jsonp在传输数据的时候,都是将callback以及传输的数据连在URL上,而URL是有长度限制的,所以jsonp适不适合传输大量数据,比如文件之类的请求。
服务器端设置header的Access-Control-Allow-Origin就适合传输大量数据的情况。
JavaScript使用jsonp实现跨域的更多相关文章
- jquery及原生javascript对jsonp解决跨域问题实例详解
jquery方式 前端: $.ajax({ url: 'http://m.xxx.tv/goLottery', data: { data: data }, type: 'GET', dataType: ...
- JSONP实现跨域
首先提出:什么是跨域?如何解决跨域? 跨域可以简单的理解为从一个域名访问另一个域名,由于javascript的同源政策的限制,出于安全的考虑,不允许浏览器这么做.比如a.com 域名下的js无法操作b ...
- MVC+Jsonp实现跨域交互
一.认识Jsonp JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式 ...
- 跨域解决方案二:使用JSONP实现跨域
跨域的实现方式有多种,除了 上篇文章 提到的CORS外,常见的还有JSONP.HTML5.Flash.iframe.xhr2等. 这篇文章对JSONP的跨域原理进行了探索,并将我的心得记录在这里和大家 ...
- 转(JSONP处理跨域事件)
前言: 由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Soc ...
- jsonp实现跨域访问
要实现JSONP跨域访问,首先就要了解什么是跨域?然后JSONP与JSON的关系? 1.什么是跨域? 跨域简单的说就是一个域名下的程序和另一个域名下的程序做数据交互.比如说:现有一个http://ww ...
- 使用JSONP实现跨域
什么是跨域? 简单的来说,出于安全方面的考虑,页面中的JavaScript无法访问其他服务器上的数据,即"同源策略".而跨域就是通过某些手段来绕过同源策略限制,实现不同服务器之间通 ...
- 跨域 - 自定义 jsonp实现跨域
问题:在现代浏览器中默认是不允许跨域. 办法:通过jsonp实现跨域 在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的.但是,在页面上引入不同域上的js脚本文件却是 ...
- 什么是同源策略,什么是跨域,如何跨域,Jsonp/CORS跨域
同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响. 可以说Web是构建在同源策略基础之上 ...
随机推荐
- WPFのGrid布局的深度理解
以下以row定义说明问题,列类似: <Grid> <Grid.RowDefinitions> <RowDefinition /> ...
- 让你提前认识软件开发(31):数据库脚本中的begin与end
版权声明:本文为博主原创文章.对文章内容有不论什么意见或建议,欢迎与作者单独交流.作者QQ(微信):245924426. https://blog.csdn.net/zhouzxi/article/d ...
- ceph 问题处理
1.三个ceph monitor节点clock skew时钟偏移问题?解决:(1)其他控制节点更改ntp.conf与controller01进行同步,如果ntpd不生效,使用date -s " ...
- 讲解Linux数据库安装
学习了linux这门课之后,就开始实践过程了,这样比较记得牢固,学以致用. 有了基本的命令,就可以试着安装数据库了. 企业环境 需要安装VMWare ESXi虚拟机,然后再在里面新建虚拟机. 镜像vm ...
- 查看Orcale数据里的表是否有变化
由于我们公司一个数据库两个应用在使用,导致一个应用修改了数据库,另一个应用用的缓存而不知道有更新还是原来的结果.原来的处理方式是采用session缓存的方式,用户登出了就清空缓存,这样只需要重新登录一 ...
- 利用Costura.Fody制作绿色单文件程序(C#程序(含多个Dll)合并成一个Exe)
原文:利用Costura.Fody制作绿色单文件程序(C#程序(含多个Dll)合并成一个Exe) 开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了.这 ...
- Nginx 反向代理 上传大文件报 413
Nginx 中上传文件限制是 2m,上传太大就报错,配置一下 client_max_body_size 1024m; 就可以上传 1G 大小文件 添加在 location 中,如果是反向代理就添加在反 ...
- spring boot 实现密码连续输入错误5次,限制十分钟内不能进行登录
我们要实现的就是,密码连续输入错误5次,就限制用户十分钟不能进行登录. 大致的流程图 数据库设计如下 DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ...
- LVM : 缩减文件系统的容量
有扩展就有缩减,我们在前文<LVM : 扩展文件系统的容量>中介绍了通过 LVM 扩展文件系统的方法,本文我们接着前文的 demo 介绍通过 LVM 缩减文件系统的方法.说明:本文的演示环 ...
- Haproxy和Nginx负载均衡测试效果对比记录
为了对比Hproxy和Nginx负载均衡的效果,分别在测试机上(以下实验都是在单机上测试的,即负载机器和后端机器都在一台机器上)做了这两个负载均衡环境,并各自抓包分析.下面说下这两种负载均衡环境下抓包 ...