一个iOS程序员眼中的跨域问题

最近公司的iOS开发任务比较少,因此本身最近开始了Web开发的任务,在用H5作了不少页面,所作的东西和以前客户端界面如出一辙,只是作好h5搬到微信上。本人开发环境:html开发ide一会用HBulder一下子用Sublime。javascript

php

了模拟真实的环境,因此HBulder新建了WebApp,跑起来能够针个人大玫瑰金上运行看效果(iphone6s plus玫瑰金)。我很傻的觉得手机上运行没错就没问题了,不会存在传说中的<b>跨域问题</b>,没想到周五下午要合并代码到Dev分支,才发现合并进去页面报错。html

只能怪本身"too young too naive",回头一想,原来App请求接口相似于C/S不存在跨域问题。而网页这种方式只要协议、域名、端口、有一个不一致就会致使跨域,因为本身所作的页面有40多,因此改起来烦的要死,问同事除了将数据放进url后来造成相似http://xxx/com?s=xx&q=yy这种形式有木有其余办法?最后找出一种快速修改的方法,见下面代码html5

修改前java

$.ajax({
type: "post",
url: early_children_url ,
data:urlJson,
success: function(data) {
console.log(storageData);
swal({
//省略...

修改后ajax

var neonataldetail = '{' +
'"babyinfoid":"' + earlyBabyInfoId + '",' +
'"days":"' + day + '",' +
'"feedingtimes":"' + feedingtimes + '",' +
'"feedingway":"' + feedingway + '",' +
'"stoolfrequency":"' + stoolfrequency + '",' +
'"urinate":"' + urinate + '",' +
'"yellowish":"' + yellowish + '",' +
'"weight":"' + weight + '"' +
'}';

var dataJson = {
"type": early_children_perinatal_type,
"neonataldetail": JSON.parse(neonataldetail)
};
var urlJson = JSON.stringify(dataJson);
$.ajax({
dataType: "jsonp",
type: "post",
url: early_children_url + "?s=" + urlJson,
success: function(data) {
console.log(storageData);
swal({
title: "提交成功",
text: "",
showCancelButton: false,
closeOnConfirm: false,
showLoaderOnConfirm: true
}, function(data) {
window.location.href = "early-children.html";
});
},
error: function() {
swal("上传失败,请检查网络后重试");
}
});

 

最后查了相关的资料发现跨域问题大致有3种解决方案:(1)、代理;(2)、JSONP(支持get请求);(3)、XHR2;(4)、CORS跨域资源共享;(5)、经过修改document.domain来解决iframe跨域问题;(6)、window.name进行跨域;(7)、HTML5的window.postMessage方法json

 

具体说明:基于浏览器的安全考虑,因为同源策略的限制,不一样域名、不一样端口、不一样协议的对象不能互相调用。(其实浏览器成功发送请求并拿回了数据 只是浏览器的同源策略 禁止了获取 )跨域

 

代理:经过统一域名下的Web服务器建立一个代理。浏览器

举例说明:www.hangzhou.com的a.html须要调用www.shanghai.com下的b.php服务,显然这违反了同源策略,因此就须要经过代码这个方法去解决问题。具体怎么作?能够在www.hangzhou.com下能够写个exchange.php。将去请求www.shanghai.com下的服务,以后将结果返回给a.html。这样访问www.hangzhou.com/exchange.php的效果等于访问www.shanghai.com的服务安全

 

JSONP:JSON with padding。是JSON的一种使用方式,适用于主流浏览器的跨域访问问题。JSONP由2部分组成:回调函数和数据

//www.hangzhou.com

<script type="text/javascript">

   function getArg(data){

      //处理数据

   }

</script>

<script type="text/javascript" src="http://www.shanghai.com/showUser.php?callback=getArg."></script>


js文件载入成功后会执行咱们在url参数中指定的函数,因此JSONP是须要服务端进行配合的。

//www.shanghai.com

<?php

     $callback = $_GET['callback'];//获得回调函数名

     $data = array('a','b','c');//要返回的数据

     echo $callback.'('.json_encode($data).')';//输出

?>

XHR2:HTML5提供的XMLHttpRequest Level2已经实现了跨域访问以及其余的一些新功能。但不适配全部浏览,好比IE10如下的版本均不支持。

此外还须要在服务端修改

header('Access-Controller-Allow-Origin:*');

header('Access-Controller-Allow-Methods:POST、GET');

window.onload = function () {

   var xhr = new XMLHttpRequest();

   //判断浏览器是否支持XHR2

   if (xhr.withCredentials === undefined) return false;



   xhr.open("get", "http://www.baidu.com");

   xhr.onreadystatechange = function () {

  if (xhr.readyState !== 4) return;//忽略未完成的调用

    if (xhr.status === 200) {

       console.log(xhr.responseText);

    }

  }

  xhr.send(null);

}

 

CORS跨域资源共享:Cross-Origin Resource Sharing定义了进行访问跨域资源时浏览器如何与服务器通讯。

<script type="">

   var xhr = new XMLHTTPRequest();

   xhr.open("get","/showUser.php");

   xhr.send();

</script>

若是使用CORS

<script type="">

   var xhr = new XMLHTTPRequest();

   xhr.open("get","http://hangzhou.com/showUser.php");

   xhr.send();

</script>

 

代码与以前的代码差异就是使用了绝对路径。服务端对于CORS的支持在于Access-Control-Allow-Origin来进行的。若是浏览器检测到相应的设置,就能够容许Ajax进行跨域的访问。

 

CORS和JSONP对比

一、JSONP只能够实现get请求,CORS能够全部类型的HTTP请求

二、CORS开发者可使用普通的XMLHTTPRequest请求和获取数据

三、JSONP支持较老的浏览器,而老版本的浏览器不支持CORS

 

 

 

经过修改document.domain来跨域

浏览器的同源策略限制之一就是不能经过Ajax去请求不一样源的文档,限制之二就是浏览器中不一样域的框架之间是不能进行js交互。

不一样框架之间能够获取window对象,可是window对象的属性和方法不可获取到。

http://www.hangzhou.com/a.html的一个frame的src是http://www.xihu.hangzhou.com/b.html这时候document.domain就能够上场了,

不过须要注意,document.domain的设定有限制,必须设置成自身或比自身更高一级的父域,且主域必须相同。

<iframe id = "iframe" src="http://xihu.hangzhou.com/b.html" onload="showUser()"></iframe>

<script type="text/javascript">

document.domain = 'hangzhou.com';//设置成主域

function showUser(){

alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象

}

</script>

在页面http://xihu.hangzhou.com/b.html也须要设置

<script type="text/javascript">

document.domain = 'hangzhou.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同

</script>

 

经过window.name来跨域

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的全部的页面都是共享一个window.name的,每一个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的全部页面中的

 

HTML5的window.postMessage方法跨域

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可使用它来向其它的window对象发送消息,不管这个window对象是属于同源或不一样源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

 

传送门:https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policyhttp://www.ruanyifeng.com/blog/2016/04/cors.html

相关文章
相关标签/搜索