1. 程式人生 > >【HAVENT原創】前端跨域一站式登錄實現 ( iframe + window.name )

【HAVENT原創】前端跨域一站式登錄實現 ( iframe + window.name )

不同的 rip 控制臺 tool 數據信息 als 前端 reat proxy

從網上搜集了一些資料,window.name 傳輸技術,關於window.name的這樣一個特性:name 值在不同的頁面(甚至不同域名)加載後依舊存在,並且可以支持非常長的 name 值(2MB)。換句話說,name屬性不會因為頁面的url變化而變化,這就給跨域提供了機會。原本是 Thomas Frank 用於解決 cookie 的一些劣勢(每個域名 4 x 20 Kb 的限制、數據只能是字符串、設置和獲取 cookie 語法的復雜等等)而發明的(詳細見原文:《Session variables without cookies》),後來 Kris Zyp 在此方法的基礎上強化了 window.name 傳輸 ,並引入到了 Dojo (dojox.io.windowName),用來解決跨域數據傳輸問題。

本示例通過 iframe 窗口重載,成功將 window.name 所需對象以字符串形式跨域傳遞到另外一個域名下,非常適用於前端跨域實現一站式登錄。

首先我們要創建一個登錄狀態返回頁面 passport.my00.com/auth.html

1 <html>
2     <script type="text/javascript">
3         window.name={"token":"用戶在本站登錄的token"}; 
4     </script>
5 </html>

然後在另一個域名拿到這個 JSON 字符串

 1 <!
DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>MY00.COM</title> 6 <script> 7 function getData ( url, fn ) { 8 var oIframe = document.createElement(iframe), 9 firstBtn
= true, 10 loadFn = function () { 11 if ( firstBtn ) { 12 // 導航回同域名根目錄下的 cross-proxy.html(空白文件,可以不存在,只是控制臺會有 404 提示),以便獲取到 name 值 13 oIframe.contentWindow.location = ‘cross-proxy.html; 14 firstBtn = false; 15 } else { 16 fn( oIframe.contentWindow.name ); 17 oIframe.contentWindow.document.write(‘‘); 18 oIframe.contentWindow.close(); 19 document.body.removeChild(oIframe); 20 oIframe.src = ‘‘; 21 oIframe = null; 22 } 23 }; 24 25 oIframe.src = url; 26 27 // 1. 第一次 iframe 加載完畢觸發事件,執行 loadFn 函數,會將 iframe 導航回 cross-proxy.html 28 // 2. cross-proxy.html 加載完畢後又會觸發事件,再次執行 loadFn 函數,此時會走 else 29 if ( oIframe.attachEvent ) { 30 oIframe.attachEvent( onload, loadFn ); 31 } else { 32 oIframe.onload = loadFn; 33 } 34 35 document.body.appendChild(oIframe); 36 } 37 38 39 // 頁面加載完畢後調用getData函數去獲取數據 40 window.onload = function () { 41 getData( ‘http://passport.my00.com/auth.html, function ( data ) { 42 console.log( data ); 43 } ); 44 } 45 </script> 46 </head> 47 <body> 48 </body> 49 </html>

以上示例完美實現跨域獲取數據信息,註意數據內容傳遞在 2M 內。下面是用 Java Spring Boot 獲取主域名的 token 並返回頁面的代碼

1     @RequestMapping("/auth")
2     public String index(HttpServletRequest request){
3         String token = LoginUtils.getToken(request);
4         token = token == null ? "" : token;
5         return "<script type=\"text/javascript\">window.name = \"{token: \"" + token + "\"}\";</script>";
6     }

【HAVENT原創】前端跨域一站式登錄實現 ( iframe + window.name )