JavaScript--跨域
跨域
什么是跨域?
跨域请求就是不同域的网站之间的文件数据之间的传送 ,由于浏览器的同源策略机制(基于安全,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性)Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准; 但用户往往需要从其他域设置或获取数据。
但是,在Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);所以 一般利用这个特性来实现‘跨域’
什么是jsonp请求?
jsonp请求跟ajax请求是不一样的,jsonp请求是可以实现跨域访问,而ajax请求是无法实现跨域访问的。那什么是jsonp?
JSONP的全称为“JSON with Padding” 可以译为‘json的装饰物’。那为什么会有叫JSONP的东西出现?我们知道现在唯一可以实现跨域的方式只有一种:引用js文件,把服务器端的数据设法装到js文件里,在客户端引用js文件,客户端就可以调用和进一步处理了。 恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP。JSONP协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。问题来了:为什么会有callback函数?
先抛开JSONP!前面说到<script>标签有跨域能力,只需外部引入js文件就可以实现跨域访问。如:
<script type="text/javascript" src="http://localhost:3000/Scripts/jquery-1.4.4.min.js"></script>
这样就可以访问到端口3000的文件了。根据上面的分析,很容易想到:利用js构造一个script标签,把json的url赋给script的src属性,然后把script标签插到DOM里,让浏览器去获取。实践如下:
function CreateScript(src) {
$("<script></script>").attr("src", src).appendTo("body")
}
添加一个按钮事件来测试一下:
$("#getJsonByHand").click(function () {
CreateScript("http://localhost:2701/home/somejson")
})
实际上,浏览器会报错。因为script标签加载完毕后会立即把相应当做js(此时传入的是json文件)执行,很明显,json里面装的只是数据,不是js合法的语句,所以会报错。怎么办呢?回到JSONP里的要点:callback函数 如果把上面的json放到一个callback函数里是最简单的方法类似这样: callback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"}) 里面的数据就是前端想要的数据。
由于服务器不知道客户端的回调函数会是什么(什么乱七八糟的名字都有),所以统一协议叫做callback 现在来添加一下回调函数:
function jsonpcallback(json) {
console.log(json)
}
改一下参数:
$("#getJsonpByHand").click(function () {
CreateScript("http://localhost:2701/home/somejsonp?callback=jsonpcallback")
})
服务器返回jsoncallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"}),我们也写了jsonpcallback方法,当然会执行。OK顺利获得了json。没错,到这里就是jsonp的全部。
简单来说:利用Script标签的跨域能力和跟服务器约定好返回callback,进行调用得到数据,这就是‘jsonp’。
来一个具体的实例:仿写百度搜索
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonp跨域</title>
<script>
document.addEventListener('DOMContentLoaded',function(){
var keyword = document.querySelector('#keyword');
var suggest = document.querySelector('#suggest');
//这是百度搜索的api cb指的是callback
var searchUrl = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?json=1&cb=getData&wd='; var timer;
keyword.oninput = function(){
var _keyword = keyword.value;
//清除上一次的搜索关键字
clearTimeout(timer);
//减少请求次数
timer = setTimeout(function(){
//动态创建script标签
var script = document.createElement('script');
script.src = searchUrl+_keyword;
document.head.appendChild(script); }, 500); } window.getData = function(data){
console.log(data);
var res = data.g; suggest.innerHTML = res.map(function(item){
return `<option value="${item.q}">${item.q}</option>`;
}).join('');
}
})
</script>
</head>
<body>
<input type="text" id="keyword" list="suggest">
<datalist id="suggest"> </datalist>
</body>
</html>
php代码:
<?php
// header("Content-type:text/html;charset=utf-8"); // 百度下拉搜索
$keyword = isset($_GET['key']) ? $_GET['key'] : '';
$url = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=' . $keyword.'&json=1&cb=getData'; $res = file_get_contents($url); // 解决乱码问题
$res = mb_convert_encoding( $res, 'UTF-8', 'UTF-8,GBK,GB2312,BIG5'); $res = str_replace(array('getData(',');'), '', $res); echo $res; ?>
可以看出:jsonp请求是单向请求, 而且是在服务器允许的情况下才可以请求数据。
再来看看另一种跨域请求的方式:CORS请求
什么是cors请求?
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器发出 XMLHttpRequest请求,从而克服了ajax只能同源使用的限制。 简单来说,就是cors和ajax搭配使用就可以实现跨域请求。
先来看具体实现:
js代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>cros跨域</title>
<script>
window.onload = function(){
var xhr = new XMLHttpRequest(); xhr.open('get','ajax/cors_fotge.php', true);
xhr.send(null);
}
</script>
</head>
<body> </body>
</html>
php代码:
<?php
header('Access-Control-Allow-Origin:*');
$res = array(
'name'=>'jjk',
'age'=>18
);
echo json_encode($res,JSON_UNESCAPED_UNICODE);
?>
在chrome中显示:

服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。
Header set Access-Control-Allow-Origin * 表示接受任意域名的请求
为了防止XSS攻击我们的服务器, 我们可以限制域,比如
Access-Control-Allow-Origin: http://blog.csdn.net
只需在php代码返回数据之前,添加 header('Access-Control-Allow-Origin:*'); 即可。
jsonp和cors之间的区别: CORS与JSONP相比,更为先进、方便和可靠。
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了
未完待续
JavaScript--跨域的更多相关文章
- JavaScript 跨域漫游
前言: 最近在公司做了几个项目都涉及到了iframe,也就是在这些iframe多次嵌套的项目中,我发现之前对iframe的认识还是比较不足的,所以就静下心来,好好整理总结了iframe的相关知识:&l ...
- 利用javascript跨域访问cookie之广告推广
在上一篇<说一说javascript跨域和jsonp>中,利用JSONP进行了跨域的数据访问,利用JS本身的跨域能力在远端生成HTML结构的方式完成了一个小广告. 在实际应用中, 跨域使用 ...
- Javascript跨域问题总结
疯狂的JSONP 关于JSON与JSONP简单总结 window.name实现的跨域数据传输 JavaScript跨域总结与解决办法 flash跨域策略文件crossdomain.xml配置详解
- 优雅绝妙的Javascript跨域问题解决方案
关于Javascript跨域问题的解决方案已在之前的一片文章中详细说明,详见:http://blog.csdn.net/sfdev/archive/2009/02/13/3887006.aspx: 除 ...
- JavaScript 跨域:window.postMessage 实现跨域通信
JavaScript 跨域方式实现方式有很多,之前,一篇文章中提到了 JSONP 形式实现跨域.本文将介绍 HTML5 新增的 api 实现跨域:window.postMessage . 1 othe ...
- JavaScript跨域实现
最近在做个上传文件的服务,其中包含一个上传的web页面.目的是想客户端页面嵌套这个web页面,然后直接将文件上传到服务器. 因为文件不同所以需要保存到的文件夹名称也不一样,所以客户端需要传递一个文件夹 ...
- thinkphp,javascript跨域请求解决方案
javascript跨域请求解决方案 前言 对于很多前端或者做混合开发的同学,我们难免会遇到跨域发起请求业务,比如A站点向B站点请求数据等等.由于最近要做一个站点集群的项目,所以具体业务要求很多个站点 ...
- JavaScript 跨域之 POST 实现。
javascript 跨域是一个很常见的问题,其中 jsonp 是一个最常用的手段,但是 jsonp 只支持 get,不支持 post,所以如果想通过 jsonp 来 post 一些数据,就头大了. ...
- jQuery(三) javascript跨域问题(JSONP解决)
加油~ --WH 一.什么是javascript跨域问题? 域:服务器域名,唯一标识(协议,域名,端口)必须保证一致,说明域相同 跨域:在一个服务器上,去访问另一个服务器上,并且得到另一个服务器返回回 ...
- JavaScript跨域解决方式
平时工作中经常被JavaScript跨域问题所困扰,其实有很多种解决方式,下面给大家介绍常用的几种: 1.jsonp解决跨域问题 客户端代码: <!DOCTYPE html> <ht ...
随机推荐
- ruby lib文件夹作用
require 'lib/test_module' #lib/test_module.rb module TestModule end
- Python之路——线程池
1 线程基础 1.1 线程状态 线程有5种状态,状态转换的过程如下图所示: 1.2 线程同步——锁 多线程的优势在于可以同时运行多个任务(至少感觉起来是这样,其实Python中是伪多线程).但是当线程 ...
- Web前端页面的浏览器兼容性测试心得(二)搭建原汁原味的IE8测试环境
如果你做的页面被老板或PM要求兼容IE8,你就值得同情了.IE8不支持HTML5,在2017年的前端界,开发者不涉及HTML5标准简直寸步难行.然而,有一个可怕的事实客观存在,那就是IE8是Win7系 ...
- 在VS2015中用C++编写可被其它语言调用的动态库DLL
转自:http://blog.csdn.net/songyi160/article/details/50754705 VS2015用C++创建动态库DLL步骤如下: (1)启动VS2015>文件 ...
- 快用Visual Studio(一)- 打开文件
在命令行中使用Visual Studio code打开文件: 打开Visual Studio code: CMD + SHIFT + P打开控制面板: 键入"shell command&qu ...
- NOIP树上问题总结
这几年考了好几次树上问题: NOIP2012 疫情控制(二分答案+倍增+贪心) NOIP2013 货车运输(最大生成树+倍增) NOIP2014 联合权值(勉强算作树形dp的傻逼题) NOIP2015 ...
- UVA 1213 Sum of Different Primes(经典dp)
题意:选择k(k<15)个唯一质数,求出和为n(n<1121)的可能数 题解:预处理dp,dp[k][n]表示使用k个素数拼成n的总方案数 就是三重枚举,枚举k,枚举n,枚举小于n的素数 ...
- 解题报告:hdu 1276 士兵队列训练问题 - 简单题
Problem Description 某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行 ...
- 字典树应用 - poj1002
字典树应用 - poj 1002 Description Businesses like to have memorable telephone numbers. One way to make a ...
- jquery实现全选/全不选
//设置全选全不选$("#checkAll").click(function () { if ($("#checkAll").attr("checke ...