最近公司的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_policy、http://www.ruanyifeng.com/blog/2016/04/cors.html