首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >javascript跨域

javascript跨域

作者头像
张炳
发布2019-08-02 16:58:50
1.4K0
发布2019-08-02 16:58:50
举报

更多详情见http://blog.zhangbing.club/Ja...

最近在项目开发的过程中遇到一些Javascript 跨域请求的问题,今天抽空对其进行总结一下,以备后用,也希望同学们在遇到类似问题的时候可以有所帮助。

Javascript跨域问题是web开发人员最常碰到的一个问题之一。所谓Javascript跨域问题,是指在一个域下的页面中通过js访问另一个不同域下的数据对象,出于安全性考虑,几乎所有浏览器都不允许这种跨域访问,这就导致在一些ajax和iframe应用中,使用跨域的web service会成为一个问题。

javascript跨域图表

那到底什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

跨域图表
跨域图表

特别注意两点:

  • 第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
  • 第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。

“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”(本段来自网络,个人觉得这段对js跨域描述得在清晰不过了)。跨域请求无处不在,平时我们在开发活动过程中,活动静态页面通过Javascript访问前端CGI就是明显的主域相同,子域不同的跨域例子,一般活动静态页面都是类似这样的(http://业务名.xx.com/act/活动...,前端CGI 是这样的(http://www.xx.com/act/活动目... 下面来看看我们都是如何处理跨域请求的:

动态创建script

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,script标签的src属性引用指向接收方的一个处理地址(后台),该地址返回的javascript方法会被执行,另外URL中可以传入一些参数,该方法只支持GET方式提交参数。我们常用FloadJS方法用的就是这种跨域方式。

alt text
alt text

使用Jquery中getScript和getJson方法实现跨域

Jquery 的getScript 和 getJson方法都可以调用跨域的js或服务端脚本,但是它们的实现原理不一样。

1.getScript 方法 语法:jQuery.getScript(url,success(response,status)) 该函数是简写的 Ajax 函数,等价于:

$.ajax({
  Type: get,
  url: url,
  dataType: "script",
  success: success
});

jQuery 1.2 版本之前,getScript 只能调用同域 JS 文件。 1.2中,您可以跨域调用 JavaScript 文件。注意:Safari 2 或更早的版本不能在全局作用域中同步执行脚本。如果通过 getScript 加入脚本,请加入延时函数。

实现跨域的原理:通过 GET 方式请求载入并执行一个 JavaScript 文件, 相当于通过src的形式的导入一个外部的js

2.getJson方法 语法:jQuery.getJSON(url,data,success(data,status,xhr)) 该函数是简写的 Ajax 函数,等价于:

$.ajax({
  url: url,
  data: data,
  success: callback,
  dataType: json
});

在jQuery 1.2 中,您可以通过使用 JSONP 形式的回调函数来加载其他网域的 JSON 数据,如 "myurl?callback=?"。jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。

实现跨域的原理:采用Jsonp原理实现跨域

到这里大家有没有发现一个问题,好像一直都在讨论http get 请求方式的跨域问题,难道post 请求就不存在跨域问题吗?其实原生态From 表单 POST 到一个后台处理脚本是不存在跨域问题,因为提交过程不牵涉到JS操作其它域名的对象,可是POST表单后,页面会刷新,给用户带来的体验不佳,这时我们经常会想到用jquery ajax post 方法来提交表单, 虽然这种方式不会刷新页面,但是会存在跨域问题。因为ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,是不允许js代码进行跨域操作,进而会发警告,所以jquery ajax post 是行不通的,可能这时有人会说,用jsonp数据类型啊,但是jsonp目前只支持get请求方式,对post请求不支持。我们在平时开发过程又不得不用post方式,因为get方式对请求的数量有大小限制,那在这种情况下如何保证用户良好的页面体验,又能解决跨域问题呢? 其实这时我们可以用最常见的document.domain + iframe 方式来实现。

document.domain + iframe

这种方式只适用主域名相同,子域名不同的情形,在我们项目开发过程,这种方式还是比较适用。

服务端代理

从上面的说明可以看到,客户端的解决方案局存在一定的局限性,而且对于ajax跨域请求,无论两个域是否属于同个基础域,都无法在客户端加以解决,也就是说如果我们要想在ajax请求中访问其他域下的数据,就只能通过服务端进行处理了。服务端的解决方案的基本原理就是,由客户端将请求发给本域服务器,再由本域服务器的代理来请求数据并将响应返回给客户端。

使用HTML 5 postMessage方式

HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。下一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。 Facebook已经使用了这个功能,用postMessage支持基于web的实时消息传递。 otherWindow.postMessage(message, targetOrigin); otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性;window.open的返回值;通过name或下标从window.frames取到的值。 message: 所要发送的数据,string类型。 targetOrigin: 用于限制otherWindow,“*”表示不作限制 a.com/index.html中的代码。 但是HTML5 在IE6, IE7浏览器下不兼容,目前移动端解决跨域问题用得比较多, PC机上用得比较少。

使用flash

如果你要读取一个外部文件,比如swf,picture,mp3等等,那么就需要一个跨域策略文件,allow-access-from domain表示允许访问的URl,如果有多个依次添加,如果允许所有就一个 allow-access-from domain = "*"就可以了。

个人小结

在项目开发过程如果能用get方式解决的就尽量使用它,毕竟get的性能也比post高,而且处理get跨域请求的方法也比较多,比如用jquery库的 getScript和getJson方法。如果提交的数据比较大,一定用post方式提交,并且考虑用户的功能体验,可以用document.domain + iframe的方式来处理。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • javascript跨域图表
  • 动态创建script
  • 使用Jquery中getScript和getJson方法实现跨域
  • document.domain + iframe
  • 服务端代理
  • 使用HTML 5 postMessage方式
  • 使用flash
  • 个人小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档