一、什么是跨域

  跨域问题来自于浏览器同源策略的限制,包括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弊端

  1. 服务器端需要改动。
  2. 只支持GET方法。
  3. 发送的不是XHR请求,无法使用各种XHR各种优势。

细说Ajax跨域的更多相关文章

  1. 浅谈linux 下,利用Nginx服务器代理实现ajax跨域请求。

    ajax跨域请求对于前端开发者几乎在任何一个项目中都会用到,众所周知,跨域请求有三种方式: jsonp; XHR2 代理: jsonp: 这种应该是开发中是使用的最多的,最常见的跨域请求方法,其实aj ...

  2. HTML5:使用postMessage实现Ajax跨域请求

    HTML5:使用postMessage实现Ajax跨域请求 由于同源策略的限制,Javascript存在跨域通信的问题,典型的跨域问题有iframe与父级的通信等. 常规的几种解决方法: (1) do ...

  3. Laravel中的ajax跨域请求

    最近接触Laravel框架ajax跨域请求的过程中遇到一些问题,在这里做下总结. 一开始发起ajax请求一直报500错误,搜索相关资料后发现Laravel要允许跨域请求可以加入Cors中间件,代码如下 ...

  4. Ajax操作如何实现跨域请求 (JSONP和CORS实现Ajax跨域的原理)

    由于浏览器存在同源策略机制,同源策略阻止ajax (XMLHttpRequest) 从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 特别的:由于同源策略是浏览器的限制,所以请求的发送和响 ...

  5. Ajax跨域问题的两种解决方法

    浏览器不允许Ajax跨站请求,所以存在Ajax跨域问题,目前主要有两种办法解决. 1.在请求页面上使用Access-Control-Allow-Origin标头. 使用如下标头可以接受全部网站请求: ...

  6. 解决ajax跨域请求 (总结)

    ajax跨域请求,目前已用几种方法实现:   1)用原生js的xhr对象实现.                var url="http://freegeoip.net/json/" ...

  7. Ajax跨域访问wcf服务中所遇到的问题总结。

    工具说明:vs2012,sql server 2008R2 1.首先,通过vs2012建立一个wcf服务项目,建立好之后.再新开一个vs2012 建立web项目,通过jQuery的ajax方法访问服务 ...

  8. JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  9. Ajax跨域:Jsonp原理解析

    推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...

随机推荐

  1. BZOJ 4269: 再见Xor [高斯消元 线性基]

    4269: 再见Xor Description 给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值. 我太愚蠢了连数组开小了以及$2^{ ...

  2. 万类之父——Object

    jdk1.8.0_144 Object类作为Java中的顶级类,位于java.lang包中.所有的类直接或者间接都继承自它.所以Object类中的方法在所有类中都可以直接调用.在深入介绍它的API时, ...

  3. Ansible进阶--playbook的使用

    一.什么是playbooksplaybooks是ansible的脚本.如同shell脚本一样,它是控制远程主机的一系列命令的集合,通过YAML语言编写.执行一些简单的任务,我们可以使用ad-hoc命令 ...

  4. 实时滚动图表绘制方法: LightningChart教程 + 源码下载

    LightningChart图形控件彻底发挥了GPU加速和性能优化的最大效应,能够实时呈现超过10亿数据点的庞大数据,为大家提供先进与快速的图表库.这里的实时图实现的比较简单,大家先试一下这个效果,熟 ...

  5. Ubuntu下的Samba服务器配置

    一. samba的安装: sudo apt-get insall samba 二. 创建共享目录: mkdir /home/phinecos/share sodu chmod 777 /home/ge ...

  6. Function与Object的关系

    这里先简单介绍一下我研究这个问题的初衷.起初我只是想研究一下原型链的基本思想.构造函数拥有prototype属性,指向它的prototype,而该构造函数的实例化对象则拥有一个[[prototype] ...

  7. 【学习笔记】Hibernate 注解 (Y2-1-9)

    Hibernate注解 1.什么是注解在类上或者方法上打上其他类型的类型元数据 @标志 使用过的注解: @override  方法重写 @Test Junit 单元测试 @Before 单元测试 @A ...

  8. WordPress 实现附件上传自动重命名但不改变附件标题

    WordPress 上传媒体文件时,默认会保持文件名不变.如果上传文件名中包含中文字符,则会造成部分浏览器显示的文件 URL 疑似乱码甚至无法访问.网上流行较广的是通过注册  wp_handle_up ...

  9. Maven常用命令及在Eclipse中的应用

    1.常用命令 mvn archetype:generate--构建项目 mvn clean--项目清理 mvn test--项目单元测试的编译 mvn compile--项目源代码的编译 mvn pa ...

  10. Sping Boot入门到实战之入门篇(一):Spring Boot简介

    该篇为Spring Boot入门到实战系列入门篇的第一篇.对Spring Boot做一个大致的介绍. 传统的基于Spring的Java Web应用,需要配置web.xml, applicationCo ...