javascript
javascript跨域实践
上次我轉載了一篇?【轉】JavaScript最全的10種跨域共享的方法?,仔細研讀,終于對跨域有了一些些了解,做了幾個demo加深印象.
1、jsonp 方式跨越:
我首先新建一個服務端頁面: jsonp.php ,放在 lovefishss.sinaapp.com 下面,具體路徑如下:http://lovefishss.sinaapp.com/cross-domain/jsonp.php,jsonp.php代碼如下
$callback = $_GET['callback']; $key = $_GET['key']; $domain = 'lovefishss.sinaapp.com'; $data = '{"domain":"'. $domain .'", "key":"'. $key .'"}'; echo $callback . '('. $data .')';我這里使用 $callback 變量保存通過 callback 傳遞過來的值(回調函數的名稱),使用 $key 保存 key 值,然后構造 json 格式字符串,最后組合輸出。
我再新建一個 jsonp.html 的請求發送頁面,我把它放在 lovefishs.sinaapp.com 下面,具體路徑:http://lovefishs.sinaapp.com/cross-domain/jsonp.html
這里我要著重說明一下,jsonp跨域方式是可以跨任何域的,不要因為我這里只是跨了子域,就被我誤導了,如果有疑惑,可以看一下我轉載的文章:【轉】JavaScript最全的10種跨域共享的方法 。
jsonp.html 代碼:
View Code <!doctype html> <html> <head> <meta charset="utf-8" /> <title>jsonp 跨域</title> <meta name="keywords" content="" /> <meta name="description" content="" /> <style type="text/css"> *{margin: 0;padding: 0;} body {text-align: left;} button {padding: 5px 10px;} .demo, .callbackResult {margin: 10px 0;padding: 0 10px;} </style> </head> <body><div class="demo"><p><button type="button" onclick="jsonp('javascript');">click me(javascript)</button></p> </div><div class="demo"><p><button type="button" onclick="jsonp('jquery');">click me(jquery)</button></p> </div><div id="J_DataView" class="callbackResult"></div></body> <script type="text/javascript" src="../static/lib/jquery.1.7.2.min.js"></script> <script type="text/javascript"> function fRandomBy(under, over){switch(arguments.length){case 1: return parseInt(Math.random() * under + 1);case 2: return parseInt(Math.random() * (over-under+1) + under);default: return 0;} }function jsonp(type){var key = fRandomBy(10000);var url = 'http://lovefishss.sinaapp.com/cross-domain/jsonp.php?callback=callback&key=' + key;switch(type){case 'javascript':var jsonpScript =document.getElementById('J_JsonpScript');if(jsonpScript){jsonpScript.parentNode.removeChild(jsonpScript);}var script =document.createElement('script');script.setAttribute('type', 'text/javascript');script.setAttribute('src', url);script.setAttribute('id', 'J_JsonpScript');document.getElementsByTagName('head')[0].appendChild(script);break;case 'jquery':$.ajax({type: 'get',url: url,data: {key: key},dataType: 'jsonp',success: callback,error: function(){}});break;} } function callback(data){var html = ['<p>domain:'+ data.domain +'</p>','<p>key:'+ data.key +'</p>'];var dataView = document.getElementById('J_DataView');dataView.innerHTML = dataView.innerHTML + html.join(''); } </script> </html>我這里寫了2種方式,一種javascript,一種借助于jquery類庫,javascript方式有助于對 jsonp 跨域方式更了解,大家可以好好的看一下源碼
jsonp 跨域方式就是這么簡單,我覺得它能夠勝任大部分的跨域方式,當然,你需要服務端的配合,如果人家服務端不配合你,不論你怎樣,都是沒用的.
jsonp 比較適用于單向的數據請求,同時還有個缺點就是,信息傳輸量太少,因為它是get方式傳遞請求數據,不及post方式數據量大,如果遇上特殊的場景,可能就不適用了,不過不用擔心,我下面還會提到其他幾種跨域方式,也會有詳細的代碼和demo參考.
2、document.domain 方式跨域
前段時間,遇到個跨域問題,就是發送當前頁面 html 內容到子域 f.domain.com 下的服務端頁面處理(生成當前頁的快照),但是當前有可能是子域 a.domain.com,或者是 b.domain.com,更或者是 c.domain.com 等等,開始想用 jsonp 方式,但是因為當前頁 html 內容比較大,已經超過了 get 提交方式的最大數據量,所以行不通;后面我用 document.domain 跨域解決了這個問題,基本方法如下:
首先,我們在 lovefishss.sinaapp.com(這里使用這個子域作為服務端處理) 域下新建一個代理文件 proxy.html ,具體地址如下:http://lovefishs.sinaapp.com/cross-domain/document.domain.proxy.html ,代碼內容如下:
<!doctype html> <html> <head> <meta charset="utf-8" /> <title>document.domain 跨域 - proxy</title> <meta name="keywords" content="" /> <meta name="description" content="" /> <style type="text/css"> *{margin: 0;padding: 0;} </style> </head> <body> </body> <script type="text/javascript" src="../static/lib/jquery.1.7.2.min.js"></script> <script type="text/javascript"> document.domain = 'sinaapp.com'; </script> </html>代碼很簡單,也就做了 2 個事,一個引入 jquery(這個我們后面會用到),一個設置 document.domain 值。這個頁面的主要作用就是供需要的頁面插入iframe,iframe的src就是這個頁面的地址。
然后,我們再在 lovefishss.sinaapp.com 下面新建一個php處理頁面,處理接收到的數據,取名 document.domain.php ,具體地址:http://lovefishs.sinaapp.com/cross-domain/document.domain.proxy.php,代買如下:
$html = $_POST['html']; $html = addslashes($html);// addslashes(string) 轉義 | StripSlashes(string) 去掉反斜杠 $key = $_POST['key']; $domain = 'lovefishss.sinaapp.com'; $data = '{"domain":"'. $domain .'", "key":"'. $key .'"}'; echo $data;這個文件主要就是接收數據,返回json字符串。
然后,我們來創建請求的頁面 document.domain.html ,該頁面處于 lovefishs.sinaapp.com 域下(不是說只能處于這個域下,隨便放在哪里都成,當然,需要與 proxy.html 是同一個主域),地址 http://lovefishs.sinaapp.com/cross-domain/document.domain.html 代碼如下:
View Code <!doctype html> <html> <head> <meta charset="utf-8" /> <title>document.domain 跨域</title> <meta name="keywords" content="" /> <meta name="description" content="" /> <style type="text/css"> *{margin: 0;padding: 0;} body {text-align: left;} button {padding: 5px 10px;} .demo, .callbackResult {margin: 10px 0;padding: 0 10px;} body .hide {display: none;} .proxyIframe {width: 0;height: 0;border: none;} </style> </head> <body><div class="demo"><p><button type="button" id="J_ClickBtn">click me(document.domain iframe)</button></p> </div><div id="J_DataView" class="callbackResult"></div><script type="text/javascript" src="../static/lib/jquery.1.7.2.min.js"></script> <script type="text/javascript"> $(document).ready(function(){function fRandomBy(under, over){switch(arguments.length){case 1: return parseInt(Math.random() * under + 1);case 2: return parseInt(Math.random() * (over-under+1) + under);default: return 0;}}function documentDomain(){// 大前提:當前域 與 目標域 主域相同,且互相設置了相同的 document.domain = 主域document.domain = 'sinaapp.com';var $this = $(this);var key = fRandomBy(10000);var ajaxUrl = 'http://lovefishss.sinaapp.com/cross-domain/document.domain.php', html = $('html').html().replace(new RegExp("<script(.|\n|\r|\t)*<\/script>", "ig"), "");var iframeSrc = 'http://lovefishss.sinaapp.com/cross-domain/document.domain.proxy.html';var $iframe = $('#J_ProxyIframe'), iframe$;var ajaxData = {html: html, key: key};if(!$iframe.length){$iframe = $('<iframe id="J_ProxyIframe" class="proxyIframe" src="'+ iframeSrc +'"></iframe>');$iframe.on('load', function(){console.log('iframe loaded');//$(this)[0].contentWindow.document.domain = 'sinaapp.com';// 異想天開的從這里控制iframe的document對象的domain值,果然是不行的。。。// 還是需要在 iframe 頁面內設置 document.domain 值// 也就是說想要通過 document.domain 方式跨域的話,必須所跨的域proxy.html文件是你能控制的,要不然你從何處設置proxy.html的document.domian呢?iframe$ = $(this)[0].contentWindow.$;proxyAjax(iframe$, ajaxData, ajaxUrl, $this);});$('body').append($iframe);}else{iframe$ = $('#J_ProxyIframe')[0].contentWindow.$;proxyAjax(iframe$, ajaxData, ajaxUrl, $this);}}function proxyAjax(i$, data, url, $btn){$btn.attr('disabled', true);i$.ajax({type: 'post',url: url,data: data,dataType: 'json',success: function(data){$btn.attr('disabled', false);callback(data);},error: function(){}});}function callback(data){var html = ['<p>domain:'+ data.domain +'</p>',//'<p class="hide">html:'+ data.html +'</p>','<p>key:'+ data.key +'</p>'];$('#J_DataView').html($('#J_DataView').html() + html.join(''));}// 綁定事件$('#J_ClickBtn').on('click', documentDomain); });</script> </body> </html>有點長,但是有注釋,仔細想想應該就能懂。這個頁面主要是發送數據,發起請求,請求的地址是我們剛才創建好的 http://lovefishs.sinaapp.com/cross-domain/document.domain.proxy.php ,因為不在同一子域下,所以我們改變當前頁的 document.domain = 'sinaapp.com'; ,然后創建一個 iframe ,src指向 proxy.html 頁面,然后為這個 iframe 綁定 load 事件,在load 后取得iframe頁面的 jquery 對象 $ ,我們要用 iframe 的 $ 來發送post請求,這樣,我們就解決了跨域發送大數據的難題,同時我們還能接收到服務端返回的json數據,有用吧,哈哈。
(2012-11-16 未完,待續)
?
?
轉載于:https://www.cnblogs.com/xmmcn/archive/2012/11/15/2771713.html
總結
以上是生活随笔為你收集整理的javascript跨域实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenGL Vertex Array
- 下一篇: Spring3.1+SpringMVC3