新近一家公司上來就讓做oa,要求嵌入公司現有系統模塊,自然而然想到模擬post單點登錄對方系統新建單點登陸頁面保存session,然現有系統都有用cookie保存用戶信息,故保存本地cookie……測試失敗。網上查詢得知,生成的cookie所在的domainName不同所致,也就是存在cookie跨域訪問問題。
因為現有相同都是ip+端口訪問方式,故無法使用二級域名共享cookie,現想到方法就是利用iframe來實現SSO,解決方法如下:
主系統通過js創建隱藏iframe(src路徑即為子系統所建ashx頁面)
//創建隱藏iframe調用單點登錄頁面實現cookie跨域共享 var sso_frm = document.createElement("iframe"); sso_frm.style.display = "none"; sso_frm.src = "@ViewBag.SSO_Url?uid=@ViewBag.uid&pwd=@ViewBag.pwd"; document.body.appendChild(sso_frm);
子系統新建一個ashx頁面,接收參數並寫入cookie (代碼略),這個方法取了個巧,相當於變相的登錄了其他系統,唯一不足之處就是在主平台登錄時需要遍歷所有權限內子系統創建iframe並登錄,這個方法可以很好地處理不同主域下的單點登錄。
擴展:
1)對於相同主域下的二級域名我們可以利用二級域名共享cookie實現單點登錄如:站點A登錄后創建cookie,設置主域:cookie.Domain = "sso.com",此時B登錄可直接獲取A創建的cookie。
2)對於不同主域下的單點登錄除了利用iframe還可以借助統一認證站點(passport.com)來實現單點登錄
例如”
站點A www.a.com
站點B www.b.com
認證站點C www.passport.com
票據:ticket加密的賬號密碼以cookie形式存在。
認證過程:假設用戶user1未曾登錄過站點AB, A登錄后判斷 a_ticket(user1加密賬號密碼)是否存在,否則跳轉站點C驗證頁面,登錄成功后生成c_ticket(加密賬號密碼)並返回A站a_ticket;而后B站點登錄會重定向站點C 驗證c_ticket驗證成功返回b_ticket並重定向B。
3) 我們也可以利用redis來替換認證站點C 處理邏輯與上述過程類似:
1.user1訪問站點A,如果a_ticket存在則正常登錄,否則判斷緩存中是否存在以user1賬號為key的值(user1賬號密碼加密),如果存在即返回該值並寫入a_ticket,如果不存在即跳轉站點A登錄頁登錄后創建user1的redis緩存並創建a_ticket;
2.user1訪問站點B,如果b_ticket存在則正常登錄,否則判斷緩存中是否存在以user1賬號為key的值(user1賬號密碼加密),如果存在即返回該值並寫入b_ticket,如果不存在則挑戰站點B登錄頁面登錄后創建
user1的redis緩存並創建b_ticket;
總結:寫的有點碎,但是大體意思應該表達清楚了,實現起來也比較簡單就不再贅述。