细说Ajax跨域
一、什么是跨域
跨域问题来自于浏览器同源策略的限制,包括DOM同源限制和Ajax同源限制,本文探讨的是Ajax跨域。Ajax跨域指的是一个页面的Ajax只能请求和当前页面同源的数据,如果发现请求到的数据不符合要求,浏览器就会阻止返回的数据。所谓同源,指的是协议、域名、端口号都必须完全相同(同一IP的不同域名也是跨域)。同源策略的主要目的是防止CSRF攻击,它可以有效地避免由于恶意攻击带来的危险,浏览器同源策略使得网络访问更加安全。
但是,实际开发与生产中,常常获取使用来自其他站点的资源,这时候就需要发起跨域请求,需要使用特殊的方法来处理,使得我们能够获得想要的数据。由此可知,跨域仅限于浏览器中,是由于浏览器对不同源数据的拦截产生的,跨域有时候是不可避免的,我们需要采取措施实现跨域请求。
二、跨域构成条件
- 浏览器限制:浏览器本身限制跨域
- 跨域请求:发起的请求是跨域的
- XHR(XMLHttpRequest)类型:请求类型是XHR请求
由上可知,解决跨域问题可以从上面三个方面着手,只需解决其一,则跨域问题也就不存在了;当然、这里的第二点跨域请求是无法避免的,因为我们谈的就是跨域请求解决档案。
三、跨域问题解决方案
- 浏览器限制方式
解决浏览器限制的方式可以通过命令:
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security --user-data-dir=E:\chrome.log来解除浏览器默认的Web安全限制;这里使用chrome浏览器做了解释。
跨域请求方式
CORS
CORS中文是“跨域资源共享”(Cross-origin resource sharing),是W3C支持的一种新的跨域方式,它与其它的方式不同的是,它是写入标准的跨域请求方式,现代浏览器普遍支持。它允许在服务器支持的前提之下,像发起普通ajax请求一样发送跨域请求。除了get请求CORS支持其它种类请求。
CORS请求分为简单请求和非简单请求两种,简单请求需要满足以下两个条件:
1)请求方法是以下三种方法之一:
- HEAD
- GET
- POST
2)HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
除此之外都是复杂请求,对于简单请求和复杂请求浏览器的处理方式不同。
对于简单请求,浏览器会在请求头中添加Origin字段来指明本次请求源,服务器会对发来的请求进行检查,对于符合条件的请求,服务器会在返回头信息中添加Access-Control-Allow-开头的相关字段。
对于非简单请求,正式请求之前会增加一次OPTIONS请求来进行”预检”,此次请求会带上请求源,服务器会校验是否符合条件,如果不符合会返回一个不带任何CORS相关的头信息字段,浏览器就会知道请求不允许,触发错误,停止继续发送请求。
CORS重点就在服务器上,只要配置了允许CORS,就可以正常发送请求,非常方便且安全性好,具体的服务器配置取决于服务端的不同实现。
服务器代理
这是一种终极的解决方案,因为限制只存在于浏览器中,在其他环境下是不存在的,服务器中中自然也不存在,所以只需要在服务器做好请求代理,请求变成同源的自然就不存在问题了。
以上是ajax跨域的主要方式。
- XHR类型
JSONP
首先最有名的一种方式就是jsonp,在学习jsonp之前首先要知道虽然浏览器有同源限制,但是有三个标签是不符合这种限制的<img>标签的src(获取图片)属性,<link>的href(获取css)属性,<script>的src(获取javascript)属性,这是由他们的自身特性所决定的。而jsonp则是利用了script标签不限制同源的特点来实现的、也就是说JSOP发出的不是XHR请求,而是script请求。
JSONP原理:
1.JSONP发送的请求是script请求,区别于XHR请求,不存在跨域的问题。
2. 普通的XHR请求返回的是JSON数据对象,JSONP返回的是一个JS脚本。
3. 请求URL的不同,请求带有callback字段
清楚了JSONP的原理之后,再看JSONP其实很简单了,下面来看一个简单的小例子。
假设客户端需要获取的JSON数据{code: 200, data: “success”},一个简单的服务端实现如下(使用node.js原生http模块)
|
1
2
3
4
5
6
7
8
9
10
11
12
|
const http = require('http');
const url = require('url');
http.createServer((req, res) => {
if (req.url.startsWith('/test')) {
res.writeHead(200, {'Content-Type': 'text/plain'});
const callback = url.parse(req.url, true).query.callback;
const result = '{code: 200, data: "success"}';
const jsonpCallback = `${callback}(${result})`
res.end(jsonpCallback);
}
}).listen(8888);
|
客户端的请求如下
|
1
2
3
4
5
6
7
|
<script>
function jsonpCallback (res) {
// 在这里处理请求结果
console.log(res);
}
</script>
<script src="http://127.0.0.1:8888/test?callback=jsonpCallback"></script>
|
综合客户端和服务端的代码可以看出,在客户端,通过请求参数传递一个jsonp方法名,在服务器端,返回的结果使用指定的jsonp方法调用来包装,这样相当于请求了一段js,而真正的返回结果可以通过函数调用参数来获取,这样就可以绕开浏览器同源限制,获取跨域请求结果。
jsonp是一种常用的跨域方式,目前有很多前端的jsonp请求封装,它们通过通过动态创建script标签来实现,我们可以直接调用。jsonp方式兼容所有的浏览器,但是只支持get请求。
JSONP弊端
- 服务器端需要改动。
- 只支持GET方法。
- 发送的不是XHR请求,无法使用各种XHR各种优势。
细说Ajax跨域的更多相关文章
- 浅谈linux 下,利用Nginx服务器代理实现ajax跨域请求。
ajax跨域请求对于前端开发者几乎在任何一个项目中都会用到,众所周知,跨域请求有三种方式: jsonp; XHR2 代理: jsonp: 这种应该是开发中是使用的最多的,最常见的跨域请求方法,其实aj ...
- HTML5:使用postMessage实现Ajax跨域请求
HTML5:使用postMessage实现Ajax跨域请求 由于同源策略的限制,Javascript存在跨域通信的问题,典型的跨域问题有iframe与父级的通信等. 常规的几种解决方法: (1) do ...
- Laravel中的ajax跨域请求
最近接触Laravel框架ajax跨域请求的过程中遇到一些问题,在这里做下总结. 一开始发起ajax请求一直报500错误,搜索相关资料后发现Laravel要允许跨域请求可以加入Cors中间件,代码如下 ...
- Ajax操作如何实现跨域请求 (JSONP和CORS实现Ajax跨域的原理)
由于浏览器存在同源策略机制,同源策略阻止ajax (XMLHttpRequest) 从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 特别的:由于同源策略是浏览器的限制,所以请求的发送和响 ...
- Ajax跨域问题的两种解决方法
浏览器不允许Ajax跨站请求,所以存在Ajax跨域问题,目前主要有两种办法解决. 1.在请求页面上使用Access-Control-Allow-Origin标头. 使用如下标头可以接受全部网站请求: ...
- 解决ajax跨域请求 (总结)
ajax跨域请求,目前已用几种方法实现: 1)用原生js的xhr对象实现. var url="http://freegeoip.net/json/" ...
- Ajax跨域访问wcf服务中所遇到的问题总结。
工具说明:vs2012,sql server 2008R2 1.首先,通过vs2012建立一个wcf服务项目,建立好之后.再新开一个vs2012 建立web项目,通过jQuery的ajax方法访问服务 ...
- JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- Ajax跨域:Jsonp原理解析
推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...
随机推荐
- 万类之父——Object
jdk1.8.0_144 Object类作为Java中的顶级类,位于java.lang包中.所有的类直接或者间接都继承自它.所以Object类中的方法在所有类中都可以直接调用.在深入介绍它的API时, ...
- 二维码开源库ZBar-MDK STM32F429移植
前两篇文章已经实现ZBar在Windows平台下的编译和使用,本文将介绍如何把ZBar移植到STM32F429,IDE使用MDK. 1. MDK工程设置 (1)不勾选Use MicroLIB ,使用I ...
- 打开word时出现the setup controller has encountered a problem during install解决办法
问题电脑为win7,office是默认安装 删除下面文件夹即可解决该问题 C:\Program Files\Common Files\Microsoft Shared\OFFICE12\Office ...
- PKUWC 2018游记
PKUWC 2018游记 标签: Day\([-inf,0)\) 停课之后一直各种浪的飞起,考试rank20+,不搞颓但是学习很没有状态.还经常带着耳机被谢总抓了好几次,然后被拉过去谈话了好几次... ...
- Dockerfile 中的 CMD 与 ENTRYPOINT
CMD 和 ENTRYPOINT 指令都是用来指定容器启动时运行的命令.单从功能上来看,这两个命令几乎是重复的.单独使用其中的一个就可以实现绝大多数的用例.但是既然 doker 同时提供了它们,为了在 ...
- Python:main函数
什么是函数? 一个程序可以包含多个模块,程序越复杂,包含的模块和功能就越多,模块细分里面包含多个类,类这个概念在任何一门面向对象语言里面都很重要,在类里面最主要的就是包含的函数,函数式实现某一个功能的 ...
- Java反射获取字节码以及判断类型
一.获取类的字节码的三种方法: 1.使用Class.class Class<?> c1=String.class; 2.使用实例.getClass() String s= Clas ...
- java9 - 异常处理
Java异常 1.异常初见 System.out.println(1/0); 运行上面语句之后打印出: Exception in thread "main" java.lang.A ...
- django新手第一课
django是基于python的一个web框架,大致结构如下: 在pycharm,python2.7,django1.8,mysql都装好的情况下,现在开始django的初试: 一.基础启动djang ...
- 大数相加(类似杭电acm1002)
/*输入两个非常大的整数(完全超出了int.long的表示范围),这个整数的长度可能超过100位,计算并输出这两个数相加的结果.*/ //自己用题目所给的案例测试,输出是正确的,也能输出正确的结果,不 ...