可跨域的單點登入(SSO)實現方案【附.net程式碼】

NO IMAGE

SSO簡介

定義:

傳統的單站點登入訪問授權機制是:登入成功後將使用者資訊儲存在session中,sessionId儲存在cookie中,每次訪問需要登入訪問的資源(url)時判斷當前session是否為空,為空的話跳轉到登入介面登入,不為空的話允許訪問。

 單點登入是一種多站點共享登入訪問授權機制,訪問使用者只需要在一個站點登入就可以訪問其它站點需要登入訪問的資源(url)。使用者在任意一個站點登出登入,則其它站點的登入狀態也被登出。簡而言之就是:一處登入,處處登入。一處登出,處處登出。

應用場景:

當一個網站系統稍微複雜一些的時候,需要對業務進行拆分,比如一個電商網站,可以將商品搜尋、商品詳情、購物車、訂單等拆分成一個個子系統,。當一個系統拆分成多個子系統的時候就需要單點登入來做授權了。

業務需求:

最近公司因為業務需要開發了一些子系統需要和主站進行整合,在網上看了好多單點登入的教程,綜合各種情況總結出了了下面的單點登入實現思路。其中用到了輪詢跳轉的思路來解決同時給多個分站寫cookie的問題。如有不妥之處歡迎各位批評指正。 

實現功能:

1.可完全跨域

2.url透明(分站跳轉不需要url傳遞token或者ticket)

3.同步登出

4.一次將cookie寫入到多個分站 

效果預覽 :

實現思路

實現難點:

這種方式的難點是:怎麼在a.com登入的時候將cookie同時寫到b.com中。我使用的方式是現在sso.com中維護一個分站集合,在登入成功後以輪詢跳轉的方式將cookie寫到各個分站中。

 具體思路:

 1.第一次訪問a.com-> 點選a.com頁面的登入按鈕->跳轉到sso.com進行登入驗證->登入成功後將資料存到cache中->然後以輪詢跳轉的方式依次訪問各個分站並將cookie寫到各個分站->最後跳轉到登入來源頁面

2.登入成功後->訪問需要登入的資源(url)->後臺傳送請求到sso.com進行cookie有效性驗證->驗證通過訪問資源

程式碼分析

 1.新建三個站點:a.com,b.com,sso.com

 2.在a.com中新建home/index頁面,如下:

第一次訪問cookie不存在,當以模擬請求的方式到sso.com/login/validateLogin進行驗證的時候返回error,頁面顯示未登入狀態

對應的view頁面如下:

 sso.com/login/validateLogin對應的程式碼:

 

3.在a.com的首頁點選登入按鈕跳轉到sso.com的登入頁面(login/index)

 

 4.sso.com中的登入程式碼如下:

 

 

5.點選登入進入到登入驗證方法

生成token,同時將使用者資訊以token為鍵儲存在cache中並設定過期時間

獲取分站集合,以重定向輪詢的方式依次向每個分站寫cookie,最後重定向到登入來源頁面

登入驗證方法如下:

a.com和b.com中的跳轉寫cookie的方法程式碼如下:

複製程式碼
  /// <summary>
/// 用跳轉的方式寫cookie
/// </summary>
/// <param name="token">授權驗證的令牌</param>
/// <param name="others">一系列分站</param>
/// <param name="main">登入成功返回的站點</param>
/// <returns></returns>
public ActionResult Jump(string token, string others, string main)
{
HttpCookie cookie = new HttpCookie("currentUser");
cookie.HttpOnly = true;
cookie.Expires = DateTime.Now.AddYears(100);//永不過期
cookie.Value = token;
Response.Cookies.Add(cookie);
//依次減掉已經寫過cookie的分站
if (!string.IsNullOrEmpty(others))
{
//獲取分站集合
var substationList = others.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
if (substationList.Count == 1)
{
return Redirect(others   "&main="   main);
}
else
{
string currentRedirect = substationList[0];
substationList.RemoveAt(0);
string otherss = string.Join(",", substationList);
return Redirect(currentRedirect   "&others="   otherss   "&main="   main);
}
}
else
{
return Redirect(main);//跳轉到登入來源頁面
}
}
複製程式碼

 

6.返回登入來源頁面a.com/home/index或者b.com/home/index

此時a.com和b.com已經都有cookie

 

7.登出(退出登入)的處理

登出直接呼叫sso.com/login/LoginOut方法,如下:

 

 

總結

 這種將使用者登入資訊以cache的方式存放在sso.com,並且將cache的鍵當做cookie的值儲存在各個分站的方式實現了跨域單點登入

這種方式的難點是:怎麼在a.com登入的時候將cookie同時寫到b.com中。我使用的方式是現在sso.com中維護一個分站集合,在登入成功後以輪詢跳轉的方式將cookie寫到各個分站中。

這種方式在實現跨域單點登入的同時也存在一些問題:

1.沒有考慮ajax登入的情況

2.沒有進行各種安全性驗證(IP信任、cookie劫持、暴力登入……)

考慮不足之處,真誠的希望大家可以提出好的想法以及補充的意見

DEMO下載

 SSODemoPro.7z