Web應用跨域訪問解決方案匯總
做過跨越多個網站的Ajax開發的朋友都知道,如果在A網站中,我們希望使用Ajax來獲得B網站中的特定內容,如果A網站與B網站不在同一個域中,那么就出現了跨域訪問問題。Ajax的跨域訪問問題是現有的Ajax開發人員比較常遇到的問題。
IE對于跨域訪問的處理是,彈出警告框,提醒用戶。如果用戶將該網站納入可信任網站,或者調低安全級別,那么這個問題IE就不會在提醒你。
FireFox等其它非微軟的瀏覽器遇到跨域訪問,則解決方案統一是拒絕訪問。
有人說,IE是主流瀏覽器,只要它能正常使用就好了。此言差已,IE雖然能夠處理,但是是有前提的,要么用戶不厭其煩地在頁面彈出警告框之后點擊是(點擊否就不執行該Ajax調用了),要么用戶將該網站納入可信任站點。這兩種做法,在企業管理系統的應用中倒是比較常見,因為系統管理員可以以行政手段保證用戶的行為。但是對于互聯網上的網站或者門戶開發,這種做法則不行。
最近遇到了這個問題,需要在跨域訪問結束之后完成使主窗口出現一些特效,搜索了一些資料,通過不斷嘗試以及在不同瀏覽器中進行兼容性測試,找到了幾個可行的Web應用跨域訪問解決方案:
1、Web代理的方式。
即用戶訪問A網站時所產生的對B網站的跨域訪問請求均提交到A網站的指定頁面(Post頁面過去),由該頁面代替用戶頁面完成交互,從而返回合適的結果。此方案可以解決現階段所能夠想到的多數跨域訪問問題,但要求A網站提供Web代理的支持,因此A網站與B網站之間必須是緊密協作的,且每次交互過程,A網站的服務器負擔增加,且無法代用戶保存session狀態。
2、on-Demand方式。
MYMSN的門戶就用的這種方式,不過MYMSN中不涉及跨域訪問問題。動態控制script標記的生成,通過修改script標記的src屬性完成對跨域頁面的調用。此方案存在的缺陷是,script的src屬性完成該調用時采取的方式時get方式,如果請求時傳遞的字符串過大時,可能會無法正常運行。不過此方案非常適合聚合類門戶使用。
3、iframe方式。
查看過醒來在javaeye上的一篇關于跨域訪問的帖子,他提到自己已經用iframe的方式解決了跨域訪問問題。數據提交跟獲取,采用iframe這種方式的確可以了,但由于父窗口與子窗口之間不能交互(跨域訪問的情況下,這種交互被拒絕),因此無法完成對父窗口效果的影響。
4、用戶本地轉儲方式。
IE本身依附于windows平臺的特性為我們提供了一種基于iframe,利用內存來“繞行”的方案,即兩個window之間可以在客戶端通過windows剪貼板的方式進行數據傳輸,只需要在接受數據的一方設置Interval進行輪詢,獲得結果后清除Interval即可。FF的平臺獨立性決定了它不支持剪貼板這種方式,而以往版本的FF中存在的插件漏洞又被fixed了,所以FF無法通過內存來完成暗渡陳倉。而由于文件操作FF也沒有提供支持(無法通過Cookie跨域完成數據傳遞),致使這種技巧性的方式只能在IE中使用。
5、我自己用于解決這類問題的方式.
結合了前面幾種方式,在訪問A網站時,先請求B網站完成數據處理,再根據返回的標識來獲得所需的結果。這種方法的缺點也很明顯,B網站的負載增大了。優點,對session也實現了保持,同時A網站與B網站頁面間的交互能力增強了。最重要的一點,這種方案滿足了我的全部需要。
總結一下,以上方案中可選擇的情況下,我最推薦on-Demand方式,在不需要提交大量數據的情況下,這種方式能夠解決您的大部分問題。
==========================================================
跨平臺跨服務器跨網站SSO(單點登錄)的方案
最近在研究SSO,看到各種復雜的解決方案覺得很疑惑,自己想出了個簡單有效的方案,大家來評評有什么問題嗎?
服務器A:網站A
服務器B:網站B
服務器C:驗證網站(驗證表中有UID和KEY兩個字段)。
1. 用戶打開網站A的頁面http://服務器A/a.aspx,檢測發現網站Session中沒有存儲用戶名UID。
2. 系統轉到驗證服務器登錄頁面,并在QUERYSTRING中附加前一個頁面的URL地址。比如http://服務器C/login.asp?URL=http://服務器A/a.aspx
3. 在驗證服務器登錄成功后更新驗證服務器的Session(超時設置為足夠長,比如1天)。然后生成一個GUID值,寫入驗證表。最后,把這個GUID值和UID保存到一個類中序列化后附加在URL中返回網站A的那個頁面。
比如http://服務器A/a.aspx? token=sadhsagdkjasgyugd7d8yweihasdiuhagsdiuashdhaiushdi
4. 網站A的頁面讀取QUERYSTRING,然后反序列化出一個類,讀取類的UID和KEY信息。然后,從數據庫中查找匹配的記錄,如果找到了則表明登錄成功,并把這條記錄的KEY更新成另外一個GUID(這樣就保證了即使這個URL被別人拿走再登錄都不能成功)。把UID寫入服務器A的Session中即可。
5. 用戶打開網站B的頁面http://服務器B/b.aspx,服務器B上沒有當前用戶的Session信息,自動轉向驗證服務器檢測是否存在Session,如果找到了表明用戶已經登錄過,再重復步驟3和4,如果沒有找到就轉到驗證服務器的登錄頁面。
巧妙之處在于:
l 網站服務器和驗證服務器都擁有一份和用戶關聯的Session,驗證到時候不需要傳任何和UID相關的信息,因此也可以跨服務器。正因為如此不需要使用cookie也解決了跨域名。
l 網站服務器和驗證服務器可以使用自己的狀態機制(不一定是Session),因此跨平臺也沒有問題。
l 用于驗證用戶的TOKEN使用GUID在每次驗證的時候都會更換,而且GUID和UID是捆綁在一起的,即使GUID碰巧對上了也不知道這個GUID對應了哪個UID。
l 通過驗證服務器的驗證后,服務器發回的token數據經過了序列化,用戶很難偽造。
(實在不放心還可以對這個token進行加密)
不知道大家是否理解了?
更新:經過網友提醒,我想到這個方案在登出的時候有嚴重問題,比如A網站登出了,我們不能通知其它網站該用戶已經登出,它再切換到其它網站又是登錄狀態(因為Session沒有過期),不過我也想到了一個解決方案。就是所有的網站都有一個專門的頁面或者服務,根據傳過來的令牌來清空這個當前用戶的Session。登出以后把所有網站的Session都清空,如果網站不是很多的情況下還好,網站一多登出就會很慢了!
更新:現在看來已經沒有什么問題了,到時候放出完整DEMO!
更新:有網友不理解為什么關閉瀏覽器所有網站退出登錄?因為Session是和用戶瀏覽器實例關聯的,而我們所有網站都使用Session,因此關閉了瀏覽器所有網站都退出了。這個和退出登錄按鈕不一樣,退出登錄按鈕需要發通知讓所有網站清除Session。
更新:我們現在把這個框架的登錄放到了各個網站中,保證登錄和退出在登錄服務器Down的情況下也能進行,只是不能進行跨站登錄罷了。登錄服務器Down還能實現本站登錄和退出。過幾天放出完整源代碼!
==========================================================
單點登陸問題-實現單點登陸的幾種方法
1 可以實現單點登陸的幾種方法
(1)基于domain的方案
這種方案是我公司目前使用的一種方案,原理:應用A在a.domain.com,B在b.domain.com,如果設cookie的時候,設domain為domain.com,那在A、B上都可以訪問到這個cookie了。(cookie的domain、path、port、version、secure相同)。
該方案特點:
1、不能夠跨域
2、在網絡中傳送用戶名和密碼
3、只支持J2EE應用
(2)基于gateway的方案
實際部署的時候,對所有應用的請求,都要通過一個gateway轉發一下,比如用一個L4的交換機頂在前面。
(3)基于tooken傳遞的方案
主要是以耶魯大學的CAS項目為基礎。
注意:你自己的應用看不到用戶的密碼。由CAS執行授權,只有CAS能看到用戶的密碼。這樣增加發安全性,因為用戶名和密碼不會通過網絡在應用間傳播。
下面是使用CAS整合的單點登錄用例
用例一:
一臺認證服務器(假定為AUTH),有兩個應用A、B,分別部署在不同的服務器上。
1) 用戶訪問A,A應用無法找到用戶的身份信息,使用redirect方法將用戶引導至http://Auth/login?service=http://A/path。
2) AUTH 顯示登錄界面,用戶輸入登錄信息,認證通過。
3) AUTH產生一個cookie(這個cookie只有AUTH上才能讀到),使用redirect方法將用戶引導回http://A/path?token=xxxxx(在有的解決方案上,這個token是通過一定編碼算法的Account信息)
4) A讀取token=xxxx的信息,獲取用戶身份。
5) 用戶訪問B。B未找到用戶的身份信息,redirect至http://AUTH/login?service=http://B/path
6) AUTH讀cookie獲取用戶身份,然后redirect回http://B/path?token=xxxx
7) B讀取token=xxxx信息,獲得用戶身份信息
用例二:
用戶訪問一個Web應用的過程。
具體的參看 http://www.9ta8.com/YaleCASServer.mht
(4)USBKey登錄
這個方案是北京點聚信息技術有限公司提供的,我也向他們的技術咨詢了相關的問題。他們的實現方式基本上是這樣的:每個使用該系統的用戶都有一個USBKey證書,在登陸系統的時候把這個證書插在計算機上。每一個網站都要通過這個證書去認證。
這樣每個登錄用戶只需插上USBKey即可進入任意受信任系統,當然訪問USBKey首先需要密碼校驗。
2 個人認為單點登陸實際上就兩種方案
首先確認要使用單點登陸,必須有一個核心,那就是不管用戶走到那個平臺,他必須要帶著他的通行證,單點登陸最關鍵的問題是用戶怎么取得、保存、使用這個通行證的問題。 用戶要取得他的通行證其實不外乎以下兩種方案:
第一種:所有的業務平臺集成在一個Portal上,去每一個平臺的時候都要帶著他的“通行證”,這就是所謂的“Tooken傳遞方案”;
第二種:使用硬件卡,就是上面所說的“USBKey登陸”;
3 單點登陸的幾個案例
(1)微軟一篇關于單點登陸的文章,他的實現是使用第一種方案。
原文:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/singlesignon.asp
(2)SharePoint Portal Server 2003 中的單一登錄
http://www.microsoft.com/china/technet/prodtechnol/sppt/reskit/c2661881x.mspx
(3)《WebCast SharePoint Portal Server 2003 Single Sign On 管理及開發》已提供下載
http://www.msotec.net/Forums/ShowThread.aspx?PostID=415
4 單點登陸的參考方法
服務器端可控JS跨域訪問解決方法
http://bbs.ad0.cn/viewthread.php?tid=302&extra=page%3D1
SSO – Single Sign-On Enterprise Security for Web Applications
http://bbs.ad0.cn/viewthread.php?tid=304&extra=page%3D1
單點登錄的簡單實現
http://bbs.ad0.cn/viewthread.php?tid=305&extra=page%3D1
PHP實現WebServices和跨域自動登陸
http://bbs.ad0.cn/viewthread.php?tid=307&extra=page%3D1
Passport跨域認證解決方法
http://bbs.ad0.cn/viewthread.php?tid=309&extra=page%3D1
Web應用跨域訪問解決方案
http://bbs.ad0.cn/viewthread.php?tid=310&extra=page%3D1
Flex或Flash的跨域訪問解決方案
http://bbs.ad0.cn/viewthread.php?tid=313&extra=page%3D1
跨域訪問新方案-PHPRPC
http://bbs.ad0.cn/viewthread.php?tid=315&extra=page%3D1
==========================================================
PHP使用P3P完成跨域COOKIE操作[轉載]
實際工作中,類似這樣的要求很多,比如說,我們有兩個域名,我們想實現在一個域名登錄后,能自動完成另一個域名的登錄,也就是PASSPORT的功能。
為了測試的方便,先編輯hosts文件,加入測試域名(C:\WINDOWS\system32\drivers\etc\hosts)
127.0.0.1 www.a.com
127.0.0.1 www.b.com
首先:創建 a_setcookie.php 文件,內容如下:
<?php
//header(‘P3P: CP=”CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR”‘);
setcookie(“test”, $_GET['id'], time()+3600, “/”, “.a.com”);
?>
然后:創建 a_getcookie.php 文件,內容如下:
<?php
var_dump($_COOKIE);
?>
最后:創建 b_setcookie.php 文件,內容如下:
<script src=”http://www.a.com/a_setcookie.php?id=www.b.com”></script>
----------------------------
三個文件創建完畢后,我們通過瀏覽器依次訪問:
http://www.b.com/b_setcookie.php
http://www.a.com/a_getcookie.php
我們會發現,在訪問b.com域的時候,我們并沒有在a.com域設置上cookie值。
然后我們修改一下a_setcookie.php文件,去掉注釋符號,a_setcookie.php即為:
<?php
header(‘P3P: CP=”CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR”‘);
setcookie(“test”, $_GET['id'], time()+3600, “/”, “.a.com”);
?>
再次通過瀏覽器依次訪問:
http://www.b.com/b_setcookie.php
http://www.a.com/a_getcookie.php
這次,你會發現在訪問b.com域的時候,我們設置了a.com域的cookie值。
==========================================================
跨域(cross-domain)訪問 cookie (讀取和設置)[轉,保存][轉載]
Passport 一方面意味著用一個帳號可以在不同服務里登錄,另一方面就是在一個服務里面登錄后可以無障礙的漫游到其他服務里面去。坦白說,目前 sohu passport 在這一點實現的很爛(不過俺的工作就是要把它做好啦,hehe)
搜狐的 SSO 需求比較麻煩,因為它旗下有好多域名:sohu.com、chinaren.com、sogou.com、focus.cn、17173.com、go2map.com,登錄用戶漫游的主要障礙也來自于此。
以前億郵的郵件系統在和別的系統整合的時候是提供一個 URL,用戶從第三方系統里面點擊這個鏈接就可以生成訪問郵件界面所需的 cookie,然后進入郵件。這個方式的確很有效,但問題是:
1. 每個外部鏈接都必須用特殊的 URL 跳轉,維護很麻煩
2. 兩個系統集成已經很麻煩了,若是集成的系統有好幾個,彼此都需要跳轉而缺乏一個中心機制就成了噩夢
3. 根本無法處理用戶直接在地址欄輸入地址進行訪問的情況
即使是跨域,上述的解決方法相對來說還是容易的。
A. 首先是所有登錄必須首先通過一個中央服務器進行認證,然后在它那里給瀏覽器種下 cookie(下面稱之為 sso cookie)
B. 當用戶訪問另外的域名 app 的時候,瀏覽器是無法直接發送 sso cookie 給服務器認證的。此時應該利用 ,動態創建一個隱藏的 ,讓其訪問 sso
C. 這個 i 的請求是可以把 sso cookie 送給 sso server 的。sso server 驗證 cookie 后,返回一個重定向頁面到 app 的某個 URL,由該 URL 設置 app cookie
D. 此時瀏覽器上可看見的頁面容器實際上也是可以和重定向回來的內容交互的。比如可以用 js 控制發現重定向頁面成功返回后,就刷新整個頁面,讓它看起來和用戶登錄后訪問沒有什么區別。
下面是真正的技巧:怎樣才能在 IE 里面跨域去設置 cookie
上述技術看起來是不是很好?但它的前提是所有的登錄都 post 到 sso server 上,認證成功后再返回 app 頁面。可我接受到的需求之一就是要支持頁面無刷新登錄。
哈!就是說本來在 chinaren.com 上提交登錄表單的 action 應該是 passport.sohu.com 這個 sso server。可是在 AJAX 大潮下,chinaren 計劃采用 HTTPRequest 提交,這個就麻煩了,因為是不能跨域來提交的。
那么解決方法就是跨域產生 cookie,即 js 發現口令校驗成功后,再在 passport.sohu.com 上種上合法的 cookie.
套用上面的跨域讀 cookie 的方案似乎很簡單去推論:就是創建一個隱含的 iframe,讓那個 iframe 去調用 passport.sohu.com 的 URL 來產生 cookie。很遺憾,此方法在 Fx 下工作的很好,但是不能在 IE 上應用。(在 IE 狀態欄上顯示 cookie 隱私警告,紅色圓底白橫杠)
我試了很多很多方法,包括創建 、 node,包括用 js 設置,但都一次次被 IE 無情的擋在了瀏覽器外。google 之,也沒有任何真正可用的答案,中文網頁要么介紹的方法是錯的,要么說無解。
最后還是在 chinaren 一哥們的幫助下,翻出了他們所使用的,以和 alumni.sohu.com 交互的方法(不知道是哪位牛人發現的),只需要設置 P3P HTTP Header,在隱含 iframe 里面跨域設置 cookie 就可以成功。他們所用的內容是:
P3P: CP=’CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR’
最后是我做的一個小小的演示:cookie 怎么在 vmx.cn 和 dup2.net 之間交互
1. http://qiuyingbo.test.vmx.cn/cookie.php
2. 隨便輸入什么,點 reset cookie,就可以看到 vmx.cn 的 cookie 已經被設上了
3. 在該頁面點連接到 http://www.dup2.net/vmx/cookie.html
4. 點’get corss-domain cookie’ .. (此時 js 會去創建一個iframe,請求 qiuyingbo.test.vmx.cn ,返回頁面把 cookie 值作為 GET 參數重定向回 dup2.net 的另外一個URL。)
5. 點 ‘display corss-domain cookie’ .. 就可以看到 vmx.cn 的 cookie 了
6. 在該頁面的輸入框中輸入其它的值,然后點 ’set cross-domain cookie’,該行為將主動設置 vmx.cn 的 cookie
7. 點鏈接回到 http://qiuyingbo.test.vmx.cn/cookie.php ,就可以看到新的值了
通過設置P3P頭來實現跨域訪問COOKIE
==========================================================
單點登錄的簡單實現
SSO 單點登錄的簡單實現 實現門戶網站單點登錄
在門戶項目中,經常會遇到如何實現單點登錄的問題,下面就本人的經驗做個總結。歡迎大家進行補充討論。
單點登錄的具體實現有很多種選擇,包括:
采用專門的SSO商業軟件: 主要有:Netgrity的Siteminder,已經被CA收購。Novell 公司的iChain。RSA公司的ClearTrust等。
采用門戶產品供應商自己的SSO產品,如:BEA的WLES,IBM 的Tivoli Access Manager,Sun 公司的identity Server,Oracle公司的OID等。
這些商業軟件一般適用于客戶對SSO的需求很高,并且企業內部采用COTS軟件如:Domino,SAP,Sieble的系統比較多的情況下采用。并結合身份管理。統一認證等項目采用。采用這些軟件一般都要對要集成的系統做些改造,如在要集成的系統上安裝AGENT。現在一般只提供常見軟件如:Domino,SAP,Sieble,常見應用服務器:weblogic,websphere等的AGENT。要先統一這些系統的認證。一般采用LDAP或數據庫。然后才能實現SSO。比較麻煩。
另外,如果不想掏銀子,也有OPEN SOURCE的SSO軟件可選:主要有:http://www.josso.org/ https://opensso.dev.java.net/ http://www.sourceid.org 等。具體怎么樣就不清楚了。
==========================================================
在PHP中實現單點登錄(Single Sign On)的一種簡單方法
單點登錄是大容量系統必備的功能,市面上有幾款昂貴的商業系統,若不是財大氣粗,恐怕用不起。
怎么樣才能簡單、經濟的實現這個功能?我們在這里探討一種可行的方案。
當前開發Web應用中,Apache + PHP + MySQL是中小型企業降低成本的必選架構,這里我們來實現PHP的單點登錄,讓這種經濟性的架構能夠擴展到的群集服務器層面。
我們的設想是將PHP的Session數據集中存儲,這樣對于不同服務器中運行的PHP來說,只有一個共有的Session數據庫,那么用戶在服務器A登錄所生成的Session數據在服務器B、C、D等服務器都可以共享,就可以免除多次登錄。但由于PHP的Session是需要Cookie的,而Cookie又是與域名相關的,所以采用這個方案的各個服務器需要有相同的域名(至少是相同的二級域名),比如:
1、所有服務器的域名都是www.whybsd.com,這個東東DNS輪詢就可以實現;這個時候,在PHP中將Cookie域名設置為www.whybsd.com即可;
2、所有服務器的域名都是以.whybsd.com結尾的三級域名,比如a.whybsd.com,b.whybsd.com等等,這個時候,在PHP中將Cookie域名設置為.whybsd.com就可以共享Cookie了。
解決了先決條件,我們現在來看看PHP的Session存儲方法,在PHP手冊說明中,有一個叫session_set_save_handler()的函數,這個函數是用來注冊用戶自定義的Session數據存儲接口的。
以下是PHP手冊自帶的示例:
代碼:
<?php
function open($save_path, $session_name) {
global $sess_save_path, $sess_session_name;
$sess_save_path = $save_path;
$sess_session_name = $session_name;
return(true);
}
function close() {
return(true);
}
function read($id) {
global $sess_save_path, $sess_session_name;
$sess_file = “$sess_save_path/sess_$id”;
if ($fp = @fopen($sess_file, “r”)) {
$sess_data = fread($fp, filesize($sess_file));
return($sess_data);
} else {
return(“”); // Must return “” here.
}
}
function write($id, $sess_data) {
global $sess_save_path, $sess_session_name;
$sess_file = “$sess_save_path/sess_$id”;
if ($fp = @fopen($sess_file, “w”)) {
return(fwrite($fp, $sess_data));
} else {
return(false);
}
}
function destroy($id) {
global $sess_save_path, $sess_session_name;
$sess_file = “$sess_save_path/sess_$id”;
return(@unlink($sess_file));
}
/*********************************************
* WARNING – You will need to implement some *
* sort of garbage collection routine here. *
*********************************************/
function gc($maxlifetime) {
return true;
}
session_set_save_handler(“open”, “close”, “read”, “write”, “destroy”, “gc”);
session_start();
// proceed to use sessions normally
?>
按照這種思路,我們只要編寫自己的處理函數并進行相應的注冊,就可以實現PHP Session數據的自定義存儲了。
具體實現可以開動你的思路,比如可以使用NFS將Session數據存儲到統一的網絡設備中,也可以將Session數據保存到一個數據庫中,讓所有服務器連接這個共享數據庫(比如MySQL)就可以了。
嗯,比較簡單,而且經濟。
更多考慮:
1、性能需要考量,特別是服務器數(引起資源占用)和用戶量(引起Session量)非常巨大的時候。
==========================================================
PHP實現WebServices和跨域自動登陸
1、webservices的php實現
主要是基于nusoap這個庫來實現的,其不但可以實現server功能還可以實現client功能,支持end point和WSDL兩種方式;連soap協議的xml消息都是自己解析的,所以完全可以脫離其他php庫支持;優點之一啊;可惜,可能有性能上的憂慮。
2、session跨域自動登陸
了解http協議特性的人都知道(參考RFC),服務端session只能是通過cookie或者get、post方法傳遞的unique id來實現的;因此欺騙服務端session的行為理論上是很容易實現的,只要你知道那個unique id及傳遞的方式;而在某個session創建之后,只要傳遞給其該唯一標示,其都是可以被認可為會話客戶的;因此,在獲得會話id的前提下任何跨域session訪問都是可能的。通過get、post方式的id容易拿到和創建,而通過cookie傳遞的就必須突破瀏覽器的跨域cookie創建限制,當然如果需要實現跨域session創建的是可控制的服務端,那問題就迎刃而解了(不過該條件下的解決方案有多種,例如互連星空就使用的URL轉向方法)。PHP實現WebServices和跨域自動登陸具體例子就不詳述了。
==========================================================
Passport跨域認證解決方法
非常簡單的Passport跨域認證解決方法:
1、架設一個PASSPORT服務器(該服務器命名為A)。所有的用戶驗證都通過此服務器驗證,其他服務器對用戶信息的獲取,用戶的身份確認,都要通過這個服務器來實現。
2、在應用服務器(該服務器命名為B)的所有需要驗證的地方判斷用戶信息是否已經驗證,如果沒有驗證,則通過 IFRAME 在用頁面放一個A服務器的驗證頁面,并傳遞一個A可以識別的標記參數,告訴A服務器是B服務器需要驗證當前用戶。
3、A服務器獲得B服務器的頁面請求后,首先檢查當前用戶是否登陸,如果沒有登陸,則停止驗證,或者反饋一個尚未登陸的頁面。
4、如果A用戶收到B服務器的也面請求后,發現當前用戶已經登陸,則生成一個隨機的長的字符串并在記錄下該字符串、生成時間、對應的用戶記錄、B服務器的標記。然后通過自動跳轉技術,訪問B服務器上的一個用戶信息驗證頁面,同時傳遞所生成的長字符串。(該頁面由A從自身記錄中獲取,由事先錄入);
5、B服務器的驗證頁面收到到所傳遞的長字符串后,在服務器端訪問A服務器的服務器端信息確認頁面,同時傳遞所收到的長字符串以及服務器標識。
6、A服務器的服務器端信息確認頁面收到信息后,通過字符串與發出請求的服務器來驗證信息的正確性:
(1)首先判斷服務器IP是否屬于該PASSPORT的服務服務器列表;
(2)通過字符串查詢記錄中是否有該字符串;
(3)通過請求服務器的IP與保留的服務器標記核對,看是否請求的IP地址是當前記錄的服務器的;
(4)判斷字符串的生成時間與當前時間比較,是否超時,超時的設置,在A服務器上設置;
(5)如果都核對無誤,則返回對應的用戶信息,否則反饋錯誤信息;
7、B服務器受到A服務器的確認信息后,根據確認信息的內容,判斷用戶是否登陸成功,如果登陸成功,則給當前用戶分配SESSION。如果不成功,則返回空白或者重復剛才的進程,重新驗證(重新驗證需要記錄次數,當次數超過一定量,則無條件停止驗證,避免死循環)
Passport跨域認證解決方法 參考:
服務器端可控JS跨域訪問解決方法
http://bbs.ad0.cn/viewthread.php?tid=302&extra=page%3D1
SSO – Single Sign-On Enterprise Security for Web Applications
http://bbs.ad0.cn/viewthread.php?tid=304&extra=page%3D1
單點登錄的簡單實現
http://bbs.ad0.cn/viewthread.php?tid=305&extra=page%3D1
PHP實現WebServices和跨域自動登陸
http://bbs.ad0.cn/viewthread.php?tid=307&extra=page%3D1
Passport跨域認證解決方法
http://bbs.ad0.cn/viewthread.php?tid=309&extra=page%3D1
Web應用跨域訪問解決方案
http://bbs.ad0.cn/viewthread.php?tid=310&extra=page%3D1
Flex或Flash的跨域訪問解決方案
http://bbs.ad0.cn/viewthread.php?tid=313&extra=page%3D1
跨域訪問新方案-PHPRPC
http://bbs.ad0.cn/viewthread.php?tid=315&extra=page%3D1
SSO-單點登錄完全解決方案
—-最全的SSO解決方案,
AJAX跨域問題,IFrame跨域問題,Cookies跨域,session跨域問題,Js跨域問題,等常見跨域問題均有提及
Ajax跨域工具: Modello.ajax
—跨瀏覽器、跨域的Ajax工具
跨域訪問新解決方案(跨域調用新方案)- PHPRPC
PHPRPC – perfect high performance remote procedure call
PHPRPC 是一個輕型的、安全的、跨網際的、跨語言的、跨平臺的、跨環境的、跨域的、支持復雜對象傳輸的、支持引用參數傳遞的、支持內容輸出重定向的、支持分級錯誤處理的、支持會話的、面向服務的高性能遠程過程調用協議。
目前該協議的最新版本為 3.0。該版本目前已有以下幾種語言的實現:
ASP:提供 JScript 和 VBScript 兩種語言的支持。
ActionScript:提供 ActionScript 2.0 和 ActionScript 3.0 兩個版本的支持。
Java:支持 JDK 1.4 以上的所有版本,它還支持 Google Android 開發包。
JavaScript:提供兩個版本的實現,一個使用純 Javascript 實現,另一個需要調用一個 swf 文件,兩個版本都支持跨域的遠程過程調用,但是使用 swf 的版本不限制參數長度,并且有更好的安全控制機制。這兩個版本已經通過完整測試的瀏覽器包括 IE 5+,Netscape 7+,Firefox,Mozilla,Opera,Safari,Epiphany,Camino 與 Konqueror。并且純 JavaScript 版本還通過了 Pocket IE、Opera Mini、Opera Mobile、iPhone、Android 等手持設備瀏覽器的測試。
.NET:支持 .NET 框架下所有的語言(如 C#、VB.NET、VC.NET、Delphi.NET 等),并且支持目前所有版本的 .NET Framework 和 .NET Compact Framework,當然它也支持 Mono。
PHP:支持 PHP4 與 PHP5,同樣支持正處于開發階段的 PHP6。
Perl:目前該版本尚不成熟,有待完善。
其中 ASP、.NET、Java 和 PHP 版本除了提供客戶端實現外,還提供了 服務器端實現。
PHPRPC 3.0下載:http://www.phprpc.org/download/phprpc_3.0.zip
PHPRPC 3.0各版本: http://www.phprpc.org/zh_CN/download/
搜索《跨域訪問新方案-PHPRPC》相關主題: 遠程調用 跨域調用 解決方案 跨域訪問 PHPRPC PHPRPC 方案 訪問
==========================================================
php sso單點登錄實現方案
http://www.dayanmei.com/blog.php/ID_1021.htm
由于已經現成有多個不同的應用,各個應用有自己的user數據,我擬定的做法是
1. 共建一個user表,通過應用綁定用戶跟user表的關系
拷貝所有現有的用戶和密碼到新表,并驗證密碼的驗證方式函數
2. 一個配置文件中設置各個應用與user表之間傳輸加密解密協議
3. 當一個用戶登錄時他首先攜帶當前的url地址或者是需要返回的url地址和通過加密協議加密后的字串提交到驗證服務器,驗證后返回加密后的狀態和票據,其中可能包含過期時間產生時間等,
如果成功,則同樣的票據通過javascript src的方式提交給其他的應用,產生cookie或者session
4. php sso單點登錄實現方案文件示例
config.inc.php 公用密鑰和驗證函數庫
ps-mm.cn域名下文件
a_setcookie.php (產生cookie 登錄當前應用)
printcookie.php (測試打印cookie)
dayanmei.com 域名下文件
驗證服務器文件
b_setcookie.php
內容:
config.inc.php
<?php
$key = ‘123456789′;
function authcode($string, $operation, $key = ”) {
$key = md5($key ? $key : $GLOBALS['auth_key']);
$key_length = strlen($key);
$string = $operation == ‘DECODE’ ? base64_decode($string) : substr(md5($string.$key), 0, 8).$string;
$string_length = strlen($string);
$rndkey = $box = array();
$result = ”;
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($key[$i % $key_length]);
$box[$i] = $i;
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == ‘DECODE’) {
if(substr($result, 0, == substr(md5(substr($result, 8).$key), 0, 8)) {
return substr($result, 8);
} else {
return ”;
}
} else {
return str_replace(‘=’, ”, base64_encode($result));
}
}
//posts transaction data using libCurl
function libCurlPost($url,$data) {
//build post string
foreach($data as $i=>$v) {
$postdata.= $i . “=” . urlencode($v) . “&”;
}
$postdata.=”cmd=_notify-validate”;
$ch=curl_init();
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$postdata);
//Start ob to prevent curl_exec from displaying stuff.
ob_start();
curl_exec($ch);
//Get contents of output buffer
//$info=ob_get_contents();
curl_close($ch);
//End ob and erase contents.
ob_end_clean();
//return $info;
}
//posts transaction data using fsockopen.
function fsockPost($url,$data) {
//Parse url
$web=parse_url($url);
//build post string
foreach($data as $i=>$v) {
$postdata.= $i . “=” . urlencode($v) . “&”;
}
$postdata.=”cmd=_notify-validate”;
//Set the port number
if($web[scheme] == “https”) { $web[port]=”443″; $ssl=”ssl://”; } else { $web[port]=”80″; }
//Create paypal connection
$fp=@fsockopen($ssl . $web[host],$web[port],$errnum,$errstr,30);
//Error checking
if(!$fp) {
//echo “$errnum: $errstr”;
}else {
fputs($fp, “POST $web[path] HTTP/1.1\r\n”);
fputs($fp, “Host: $web[host]\r\n”);
fputs($fp, “Content-type: application/x-www-form-urlencoded\r\n”);
fputs($fp, “Content-length: “.strlen($postdata).”\r\n”);
fputs($fp, “Connection: close\r\n\r\n”);
fputs($fp, $postdata . “\r\n\r\n”);
//loop through the response from the server
while(!feof($fp)) {
$info[]=@fgets($fp, 1024);
}
//close fp – we are done with it
fclose($fp);
//break up results into a string
$info=implode(“,”,$info);
}
return $info;
}
?>
Pirntcookie.php
<?php
print $_COOKIE['test'];
?>
A_setcookie.php
<?php
header(‘P3P: CP=”CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV”‘);
include(‘config.inc.php’);
$string = explode(“\n”,authcode($_GET['string'],’DECODE’,$key));
setcookie(“test”, $string[1], time()+3600, “/”, “.ps-mm.cn”);
?>
B_setcookie.php
<script src=”http://www.ps-mm.cn/a_setcookie.php?string=f20Bq5QGXqSRKlpwuTfB”></script>
來自: http://blog.csdn.net/fangaoxin/article/details/6929415